1.什么是Synchronized
JAVA 中的一个保留字,用于标识同步锁。简单来说,在Synchronized的作用域内,可以保证只有单个线程串行访问(通常情况下),不会出现多线程的读写结果与预期不相符的行为。
2.在什么时候使用?
在专业书籍中对于什么时候使用,有很专业的描述。
简单来说,当修改共享变量时,需要考虑使用Synchronnized。
3.实现原理
1.锁的是什么:对象
public class synA {
private static final Object obj=new ();
public synchronnized void funA(){} ---锁了this
public void funB(){
.......
synchronnized{ ------锁了this
....
}
......
}
public void funC(){
.......
synchronnized(obj){ ------锁了obj
....
}
......
}
}
锁对象的意思是:因为这部分是使用C来实现的,我们借用java的概念可以理解为: 对象---->ObjectMonitor属性------>_owner 属性 ,更详细的可以参考Synchronized源码解析
竞争到锁:即_owner=当前线程
释放锁:_owner属性为空,或者线程死掉。
4.锁怎么优化:
由于锁的实现是悲观锁-也叫重量级锁,就是说其他线程需要阻塞等待当前线程释放掉后,才能进行下一步处理。这个阻塞实际上就是个死循环。
这个会有消耗,那怎么办呢?
hotspot的作者就去看啊,发现:呀!!!竟然大部分情况下都没有竞争
所以------有了所谓的偏向锁:
偏向锁:就是在对象头的位置(_owner)写上当前线程。由于一般没有竞争,所以首先检查这个值是不是当前线程。如果是,就说明是当前线程持有锁。在少数情况下,需要竞争,就写写看。写成功了,就说明竞争到锁了。这里的写写看涉及到一个概念(CAS)。CAS就是一个由硬件提供的原子型指令,跟setnx这些原子指令一样,因为毕竟有可能是存在竞争的, 所以还是要保证这种原子指令。
如果竞争不到锁,说明这里存在多线程在竞争,那说明偏向锁现在不适用了。需要上升。
轻量锁 上场了:
所谓轻量锁就是把阻塞等到改成了自旋等待,就是死循环一段时间,然后重试。
(这一段是我自己意淫,暂未正式):大概是等待一段时间,试一下;重试个几次,发现还不行,那还不如切换到别的线程去呢;
所以有了重量级锁-阻塞等待。
就有了 线程的切换、唤醒等一系列的消耗