synchronized详解

synchronized可以锁方法也可以锁对象

1.synchronized锁代码块

this,代表SynchronizedObjectLock这个实例化对象 instance。因为t1与t2用的是一个实例化对象,所以只有一把锁

因为block1与block2是两把锁所以。。。。

因为锁的是类,而类加载模板只有一个所以只有一把锁。

2.方法锁

这里锁的是方法,默认就是this,也就是锁的实例化对象instence

这里锁的是静态方法,也就相当于锁的是类了,也就是只有唯一一把锁。

synchronized的性质

1.可重入性

也就是,定义一个方法是synchronized后。里面的方法也可以在这个方法没有完成前使用这个锁。这样就避免了死锁。

2.不可中断性

如果这个锁被B线程获取,如果A线程想要获取这把锁,只能选择等待或者阻塞,直到B线程释放这把锁,如果B线程一直不释放这把锁,那么A线程将一直等待。

相比之下,未来的Lock类,可以拥有中断的能力(如果一个线程等待锁的时间太长了,有权利中断当前已经获取锁的线程的执行,也可以退出等待)


synchronized原理

在.class文件里可以看到

Monitorenter和Monitorexit指令,会让对象在执行,使其锁计数器加1或者减1。每一个对象在同一时间只与一个monitor(锁)相关联,而一个monitor在同一时间只能被一个线程获得,一个对象在尝试获得与这个对象相关联的Monitor锁的所有权的时候,monitorenter指令会发生如下3中情况之一:

1)monitor计数器为0,意味着目前还没有被获得,那这个线程就会立刻获得然后把锁计数器+1,一旦+1,别的线程再想获取,就需要等待

2)如果这个monitor已经拿到了这个锁的所有权,又重入了这把锁,那锁计数器就会累加,变成2,并且随着重入的次数,会一直累加

3)这把锁已经被别的线程获取了,等待锁释放

monitorexit指令:释放对于monitor的所有权,释放过程很简单,就是讲monitor的计数器减1,如果减完以后,计数器不是0,则代表刚才是重入进来的,当前线程还继续持有这把锁的所有权,如果计数器变成0,则代表当前线程不再拥有该monitor的所有权,即释放锁。


synchronized的缺点

效率低:锁的释放情况少,只有代码执行完毕或者异常结束才会释放锁;试图获取锁的时候不能设定超时,不能中断一个正在使用锁的线程,相对而言,Lock可以中断和设置超时

不够灵活:加锁和释放的时机单一,每个锁仅有一个单一的条件(某个对象),相对而言,读写锁更加灵活

无法知道是否成功获得锁,相对而言,Lock可以拿到状态,如果成功获取锁,....,如果获取失败,.....

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。