首页 > 其他分享 >synchronized关键字

synchronized关键字

时间:2023-02-08 21:45:20浏览次数:43  
标签:同步 monitor synchronized 对象 关键字 线程 监视器

1、当一个线程进入一个对象的一个synchronized方法后,其他线程可以进入此对象的非同步方法,不可进入此对象此同步方法,也不可进入此对象其他同步方法。同步监视器的意思是:线程开始执行同步代码块或者同步方法时,必须先要获得对同步监视器的锁定。任何时刻只能有一个线程获得对同步监视器的锁定,synchronized代码块的监视器是括号里的obj对象,synchronized方法的同步监视器是this。例如Test t = new Test(),t.f(),如果f是同步方法,则同步监视器是t(即调用该方法的对象),即线程获得的锁对象是t

2、可重入锁和synchronized的基本特性

1) 同步代码块使用monitorenter和monitorexit指令实现,monitorenter指令插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置,jvm需要保证每一个monitorenter都有一个monitorexit与之对应。任何对象都有一个monitor与之相关联,一个monitor被持有之后,对象将处于锁定状态。根据jvm规范,在执行monitorenter指令前,首先要获得对象的锁,获取成功后,把锁的计数器加1,相应的,在执行monitorexit指令时,会将锁计数器减1,当计数器为0时,锁就被释放。如果获取对象锁失败,当前线程就要阻塞等待,直到对象锁被另外一个线程释放为止。

2) 同步方法,虚拟机可以从方法表中的ACC_SYNCHRONIZED访问标志得知一个方法是否为同步方法,当方法调用时,调用指令会检查ACC_SYNCHRONIZED访问标志是否被设置了,若被设置了,执行线程就要先成功持有monitor,然后才能执行方法,最后当方法完成时释放monitor,在方法执行期间,执行线程持有了monitor,其他任何线程都无法再获取到同一个monitor。

  在java设计中,每一个对象自打娘胎里出来就带了把看不见的锁,即monitor锁。一个monitor只能被一个线程拥有。线程获取monitor成功,就成为该监视器对象的拥有者。monitor是线程私有的数据结构,每一个线程都有一个可用monitor record列表,同时还有一个全局可用列表。每一个被锁住的对象都会和一个monitor关联。

  在使用synchronized的时候,当一个线程请求一个由其他线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁就会成功,否则阻塞。一个例子:在一个synchronized修饰的方法或代码块的内部调用本类的其他synchronized修饰的方法或代码块时,是永远可以得到锁的。为什么要引入可重入锁这种机制?这种锁的概念就是:自己可以获取自己的内部锁。假如一个线程T获得了对象A的锁,那么该线程如果在未释放前再次请求该对象的锁时,如果没有可重入锁的机制,是不会获取到锁的,这样就会出现死锁的情况。就如上述代码,线程T在执行到method1内部的时候,由于该线程已经获取了该对象syncDubbo的对象锁,当执行到调用method2时,会再次请求该对象的对象锁,如果没有可重入锁的机制,就会出现死锁。

  synchronized其他特性:出现异常时,其持有的锁会自动释放。另外,可以将任意对象作为监视器。

    synchronized实现原理:本质上是对一个对象监视器进行获取,执行方法的线程必须先获取到该对象的同步监视器才能进入同步块或者方法块,没有获取到监视器的线程将会被阻塞在同步块和同步方法的入口处,进入BLOCKED状态,在同步队列中等待。

  可以看出,Object由synchronized保护,任意线程对Object的访问首先要获得Object的监视器。如果获取失败,线程进入同步队列,进入BLOCKED状态。当之前获得了锁的线程释放了锁,该释放操作唤醒在同步队列中的线程,使其重新尝试对监视器的获取。

  jvm对synchronized的优化:jdk1.6以后为了减少获得和释放锁带来的性能消耗引入了偏向锁和轻量级锁。下边就学习下偏向锁,轻量级锁,重量级锁和自旋锁。先看下synchronized锁的存放位置,synchronized用的锁是存在java对象头里的,如果对象是数组类型的,则jvm用3个字宽(Word)存储对象头,如果是非数组类型的,则用2字宽存储对象头。32位虚拟机中,1字宽等于4字节即32比特。

java对象头里的Mark Word里默认存储对象的hashcode、分代年龄和锁标记位。32位jvm的Mark Word里默认存储结构如下图

 

当一个线程访问Object的synchronized方法时,另一个线程能访问object的非Synchronized方法,但是不能访问object的其他Synchronized方法。

如果synchronized修饰普通方法,那么锁监视器是当前实例对象,如果类的两个不同实例就没有这种约束了。例如account类的实例account1和account2,对account1操作只能获取account1的对象锁。

如果synchronized修饰static方法,相当于在类上加锁,只要是这个类产生的对象,在调用这个静态方法时都会产生互斥。该类的所有实例对象公用一个监视器

 

标签:同步,monitor,synchronized,对象,关键字,线程,监视器
From: https://www.cnblogs.com/MarkLeeBYR/p/17103384.html

相关文章

  • MySQL DISTINCT关键字详解:用法、实际应用和与GROUP BY的区别
    "Successisnothowhighyouhaveclimbed,buthowyoumakeapositivedifferencetotheworld."成功不在于你爬得多高,而在于你对世界做出了多大的积极影响。-Roy......
  • void关键字
    void函数的形参用void*,表示接受任意数据类型的指针。注意:l不能用void声明变量,它不能代表一个真实的变量,但是,用void*可以。l不能对void*指针直接解引用(需要转换成......
  • 35-static关键字详解
    static带static是和类一起加载的,能直接调用反之需要用new抽取对象,然后再调用publicclassTest{privatestaticintage;//静态变量privateintscore;......
  • [你必须知道的.NET]第十六回:深入浅出关键字---using全接触
    [你必须知道的.NET]第十六回:深入浅出关键字---using全接触 本文将介绍以下内容:using指令的多种用法using语句在Dispose模式中的应用  1. 引言在.NET大家庭......
  • Synchronized和Volatile的对比
    Synchronized和Volatile是并发中的两大关键字,有相似性和不同点。Synchronized更详细介绍参考https://www.cnblogs.com/spark-cc/p/17069585.htmlvolatile简单来说就是轻......
  • 数据库基础3:as关键字、distinct去重关键字、where条件查询、排序、分页查询
    1.as关键字在使用SQL语句显示结果的时候,往往在屏幕显示的字段名并不具备良好的可读性,此时可以使用as给字段起一个别名。--使用as给字段起别名selectidas序号,n......
  • PHP 的glob()函数 和 关键字global
    glob()函数phpglob()函数返回匹配指定模式的文件名或目录。因此我们可以使用glob函数来查找文件,也可以实现目录的遍历。函数说明:arrayglob(string$pattern[,int......
  • DAY 253 Java transient关键字
    1.transient的作用及使用方法     我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必......
  • final关键字--Java基础052
    /*final(最终、修饰符)final关键字的用法:1.final关键字修饰一个基本类型的变量时,该变量不能重新赋值,第一次的值为最终的。2.fianl关键字修饰一个引用类型变量时,该......
  • instanceof关键字--Java基础051
    /*instanceof关键字instanceof关键字的作用:判断一个对象是否属于指定的类别。instanceof关键字的使用前提:判断的对象与指定的类别必须要存在继承或者实现的关系。instanceo......