锁的分类

Java中有各式各样的锁,大致可以分为以下几类

  • 公平锁 / 非公平锁
  • 可重入锁
  • 互斥锁 / 共享锁
  • 乐观锁 / 悲观锁
  • 分段锁
  • 偏向锁 / 轻量级锁 / 重量级锁
  • 自旋锁

公平锁 / 非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。 对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。 对于Synchronized而言,也是一种非公平锁。

可重入锁

可重入锁又叫递归锁, 同一个线程在外层方法获取锁时,进入内层方法自动获取锁不会被阻塞
ReentrantLock和Synchronized都是可重入锁

以下例子,如果synchronized不是可重入锁的话就有可能造成死锁

synchronized void setA() throws Exception{
    Thread.sleep(1000);
    setB();
}

synchronized void setB() throws Exception{
    Thread.sleep(1000);
}

互斥锁 / 共享锁

  • 互斥锁:X锁,只能被一个线程持有,写锁是互斥锁
  • 共享锁:S锁,可以被多个线程持有,读锁是共享锁

乐观锁 / 悲观锁

乐观锁和悲观锁并不是具体指什么类型的锁,而是对待并发同步的方式

  • 悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。
  • 乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。

悲观锁在Java中是用各种具体的锁来实现的,乐观锁是无锁,采用CAS算法实现,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

分段锁

分段锁不是一种具体的锁,而是一种锁的设计,通过细化锁的粒度提高性能

Java7中的ConcurrentHashMap就采用了分段锁的设计,当进行put操作时,先通过hashcode找到要插入的分段中,然后对该分段进行加锁。当多个线程进行put操作时,只要不是在同一个分段中就能执行并行插入

偏向锁 / 轻量级锁 / 重量级锁

  • 偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
  • 轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
  • 重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。

自旋锁

尝试获取锁的线程不会阻塞而是采用循环的方式获取锁,可以减少线程切换的切换但是会消耗CPU

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

推荐阅读更多精彩内容

  • 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章来汇总下各种锁的分类。 公平锁/非公平锁可重入锁...
    激情的狼王阅读 850评论 0 17
  • https://www.cnblogs.com/qifengshi/p/6831055.html[https://...
    屎倒淋头还嚼便阅读 251评论 0 2
  • 股社区 8月7日 12:33来自微博weibo.com 现在的舆情太敏感了,容不得半点批评和抱怨,最近好几篇大热的...
    newzr阅读 507评论 0 0
  • 今天下午一放学接了女儿,刚刚回到家,她黄阿姨领着小孙女来我家借幼儿园的被子。我问女儿可以吗?她说:妈妈可以,我已经...
    赵奕嘉阅读 135评论 0 1
  • 夏季的大暴雨侵犯了熟睡的村庄 村庄没能阻挡 雨水的村庄是湿润的青草塘 野合的好地方 没有一种粗暴是不合适的 没有一...
    JEASIR阅读 8,428评论 1 6