首先Sychronized的具体实现实在jvm下具体实现的,Sychronized并不是单纯的加锁,因为锁是分为很多种类型的,在不同的场景下需要不同的锁,因此Sychronized在jdk1.8里实现了多种情景下的加锁。
1.在最开始对一段程序进行加锁的时候使用的是乐观锁,所谓乐观锁就是认为该锁发生冲突的概率低,如果发现该锁的冲突概率比较高,就会自动转为悲观锁
2.Sychronized不是读写锁(具体的我也暂时没搞懂)。
3.Sychronized开始的时候是轻量锁,如果锁被持有时间过长会转换为重量级锁
4.非公平锁(不支持先来后到,而是概率相等)
5.可重复性(允许重复加锁)
6.Sychronized的轻量级锁大概率是自旋锁,为重量级锁大概率是挂起等待锁
加锁的工作过程
无锁→偏向锁→自旋锁→重量级锁
偏向锁:对象头设置一个“偏向锁标记”,只做标记,用通俗的话来说就是赌,赌没有另一个线程竞争这个锁,不会发生竞争,如果真的发生了竞争就会进行情景分析,自动进行锁的升级。
举一个生活中的例子:品如是个美女,他看上了个小哥哥世贤,但是不和人家谈恋爱只搞暧昧,这样做成本是比较低的,不会出现分手后痛哭流涕,无法自拔的情况,但是有一天出现了一个新的妹子,叫艾莉,艾莉也和史贤搞暧昧,并且两个人出现了竞争,品如担心艾莉会抢走世贤,就立马给世贤表白,两个人就在一起了~~结束了罪恶的一生
偏向锁简而言之就是用最好的打算,最低的成本去加锁,同时又做了最坏的打算,如果真的发生竞争就会立即加锁。
1.如果出现了竞争,并且竞争比较小,就会进入轻量级锁,通过cas自动实现,属于用户态的操作,不涉及内核态和用户态的切换,也不设计线程的阻塞和调度,但是又保障了更高效的获取到锁。(轻量级锁在使用中另外的线程会一直运转,如果拥有锁的线程释放了锁,其他的线程就会立马拿到该锁,这个方法对cpu的消耗会增加,因为一个线程在使用锁的时候另外的线程会一直运行尝试拿到锁,但是由于线程数量少,不会消耗太多的cpu)
2.如果锁的竞争和冲突比较大,线程比较多,如果再使用轻量级锁会对cpu消耗过大,因此此时会进行锁膨胀,变成重量级锁,重量级锁是在一个线程使用锁的时候,会把其他的线程进行阻塞,被阻塞时,不会消耗cpu,但是唤醒一个线程的时候都需要系统来帮忙,这就需要从用户态转化为内核态,转换需要时间,因此重量级锁性能上会下降,但是减少了cpu的消耗。