synchronized深度解析

n个对象n个锁

关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁。

多个线程访问同一对象,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁。

多个线程访问多个对象,则JVM会创建多个锁。

同步与非同步

只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本没有同步的必要。

A线程先持有object对象的Lock锁,B线程可以以异步的方式调用object对象的非synchronized类型的方法。

A线程先持有object对象的Lock锁,B线程如果在这时调用obkect对象中的synchronized类型的方法则需等待。

脏读

当A线程调用object对象加入synchronized关键字的X方法时,A线程就获得了X方法所在对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,而B线程如果调用声明了synchronized关键字的非X方法时,必须等A线程将X方法执行完,也就是释放对象锁后才可以调用。所以一般对变量进行getValue()和setValue()时,两个方法都需要加synchronized关键字来防止脏读。

脏读一定会出现操作实例变量的情况下,这就是不同线程“争抢”实例变量的结果。

synchronized锁重入

关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁的。这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。

当存在父子类继承关系时,子类是完全可以通过“可重入锁”调用父类的同步方法的。

异常释放锁

当一个线程执行的代码出现异常时,其持有的锁会自动释放。

同步不继承

子类重写父类的synchronized方法时,如果子类方法未加synchronized关键字,则此方法不具有同步性。

synchronized代码块

当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的“对象监视器”是一个。

synchronized(this)和synchronized(非this)

和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的,且synchronized(this)同步代码块对sychronized同步方法或其他synchronized(this)同步代码块调用呈阻塞状态。

使用同步代码块非this对象,则synchronized(非this)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁。当持有“对象监视器”为同一个对象x的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码,这一现象从反面说明了synchronized(非this对象x)与synchronized(非this对象y)也是异步的

synchronized(x)3个结论

当多个线程同时执行synchronized(x)同步代码块时呈同步效果。

当其他线程执行x对象方法里面的synchronized同步方法时呈同步效果。

当其他线程执行x对象方法里面的synchronized(this)代码块时也呈同步效果。

静态synchronized方法与synchronized(class)代码块

静态synchronized方法是给Class类上锁,可以对类的所有对象实例起作用。synchronized(class)代码块的作用其实和synchronized static 方法的作用一样。

猜你喜欢

转载自blog.csdn.net/qq_30051265/article/details/81706782
今日推荐