前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java杂谈之各种锁

java杂谈之各种锁

作者头像
你呀不牛
发布2021-05-28 11:20:56
5490
发布2021-05-28 11:20:56
举报
文章被收录于专栏:我要变牛我要变牛我要变牛

1.乐观锁和悲观锁

悲观锁和乐观锁并不是某个具体的锁而是一种并发编程的基本概念。乐观锁和悲观锁最早出现在数据库的设计当中,后来逐渐被 Java 的并发包所引入。

悲观锁

悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观地认为,不加锁的并发操作一定会出问题。

乐观锁

乐观锁正好和悲观锁相反,它获取数据的时候,并不担心数据被修改,每次获取数据的时候也不会加锁,只是在更新数据的时候,通过判断现有的数据是否和原数据一致来判断数据是否被其他线程操作,如果没被其他线程修改则进行数据更新,如果被其他线程修改则不进行数据更新。

2.公平锁和非公平锁

公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。

非公平锁

非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。ReentrantLock 提供了公平锁和非公平锁的实现。

公平锁:new ReentrantLock(true) 非公平锁:new ReentrantLock(false) 如果构造函数不传任何参数的时候,默认提供的是非公平锁。

3.独占锁和共享锁

独占锁

独占锁是指任何时候都只有一个线程能执行资源操作。

共享锁

共享锁指定是可以同时被多个线程读取,但只能被一个线程修改。比如 Java 中的 ReentrantReadWriteLock 就是共享锁的实现方式,它允许一个线程进行写操作,允许多个线程读操作。

4、可重入锁

可重入锁指的是该线程获取了该锁之后,可以无限次的进入该锁锁住的代码。

5、 自旋锁

自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗 CPU。自旋锁等待虽然避免了线程切换的开销,但是要占用CPU处理时间,因此如果锁被占用的时间很短。自旋等待的效果就很好,反之,如果锁被占用的时间很长,那么自旋的线程就只会白白消耗CPU资源,而不会做任何有用的工作,反而带来性能的浪费。因此等待时间一定要有一定限度,如果自旋超过一定次数没有获得锁,就应该挂起线程

6、自适应锁

从JDK1.6之后引入了自适应锁,自适应锁意味着自旋时间不固定了,而是由前一次在同一个锁上的自旋时间及锁拥有者状态来决定,如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程在执行中,,那么虚拟机就会认为这次自旋也很有可能再次成功,进而将它允许自旋等待持续更长时间,比如循环100次。如果某个锁。自旋成功次数很少,,那以后要获取这个锁时就可能省略掉自旋过程。有了自适应锁,随着程序运行和性能监控的不断完善,虚拟机对程序锁的状态预测越来越准确,虚拟机变得越来越聪明了

7、轻量级锁

轻量级锁指的轻量是相对于使用操作互斥量实现的传统锁,一般是在无竞争的情况下使用CAS操作去消除同步使用的互斥量。

8、偏向锁

偏向锁会偏向第一个获取到它的线程,如果在接下来的过程中,该锁没有被其他线程获取,则持有偏向锁的线程将永远不需要再进行同步。

常见相关问题

1. synchronized 是哪种锁的实现?为什么?

答:synchronized 是悲观锁的实现,因为 synchronized 修饰的代码,每次执行时会进行加锁操作,同时只允许一个线程进行操作,所以它是悲观锁的实现。

2. new ReentrantLock() 创建的是公平锁还是非公平锁?

答:非公平锁,查看 ReentrantLock 的实现源码可知。

/**
 * Creates an instance of {@code ReentrantLock}.
 * This is equivalent to using {@code ReentrantLock(false)}.
 */
public ReentrantLock() {
    sync = new NonfairSync();
}
3. synchronized 使用的是公平锁还是非公平锁?

答:synchronized 使用的是非公平锁,并且是不可设置的。这是因为非公平锁的吞吐量大于公平锁,并且是主流操作系统线程调度的基本选择,所以这也是 synchronized 使用非公平锁原由。

4. 为什么非公平锁吞吐量大于公平锁?

答:比如 A 占用锁的时候,B 请求获取锁,发现被 A 占用之后,堵塞等待被唤醒,这个时候 C 同时来获取 A 占用的锁,如果是公平锁 C 后来者发现不可用之后一定排在 B 之后等待被唤醒,而非公平锁则可以让 C 先用,在 B 被唤醒之前 C 已经使用完成,从而节省了 C 等待和唤醒之间的性能消耗,这就是非公平锁比公平锁吞吐量大的原因。

5. volatile 的作用是什么?

答:volatile 是 Java 虚拟机提供的最轻量级的同步机制。当变量被定义成 volatile 之后,具备两种特性:

保证此变量对所有线程的可见性,当一条线程修改了这个变量的值,修改的新值对于其他线程是可见的(可以立即得知的); 禁止指令重排序优化,普通变量仅仅能保证在该方法执行过程中,得到正确结果,但是不保证程序代码的执行顺序。

6. volatile 对比 synchronized 有什么区别?

答:synchronized 既能保证可见性,又能保证原子性,而 volatile 只能保证可见性,无法保证原子性。比如,i++ 如果使用 synchronized 修饰是线程安全的,而 volatile 会有线程安全的问题。

7. CAS 是如何实现的?

答:CAS(Compare and Swap)比较并交换,CAS 是通过调用 JNI(Java Native Interface)的代码实现的,比如,在 Windows 系统 CAS 就是借助 C 语言来调用 CPU 底层指令实现的。

8. CAS 会产生什么问题?应该怎么解决?

答:CAS 是标准的乐观锁的实现,会产生 ABA 的问题。ABA 通常的解决办法是添加版本号,每次修改操作时版本号加一,这样数据对比的时候就不会出现 ABA 的问题了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 你呀不牛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.乐观锁和悲观锁
    • 悲观锁
      • 乐观锁
      • 2.公平锁和非公平锁
        • 公平锁
          • 非公平锁
          • 3.独占锁和共享锁
            • 独占锁
              • 共享锁
              • 4、可重入锁
              • 5、 自旋锁
              • 6、自适应锁
              • 7、轻量级锁
              • 8、偏向锁
              • 常见相关问题
                • 1. synchronized 是哪种锁的实现?为什么?
                  • 2. new ReentrantLock() 创建的是公平锁还是非公平锁?
                    • 3. synchronized 使用的是公平锁还是非公平锁?
                      • 4. 为什么非公平锁吞吐量大于公平锁?
                        • 5. volatile 的作用是什么?
                          • 6. volatile 对比 synchronized 有什么区别?
                            • 7. CAS 是如何实现的?
                              • 8. CAS 会产生什么问题?应该怎么解决?
                              相关产品与服务
                              应用性能监控
                              应用性能监控(Application Performance Management,APM)是一款应用性能管理平台,基于实时多语言应用探针全量采集技术,为您提供分布式性能分析和故障自检能力。APM 协助您在复杂的业务系统里快速定位性能问题,降低 MTTR(平均故障恢复时间),实时了解并追踪应用性能,提升用户体验。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档