Java中各种锁的详解

导读
今天和同事探讨多线程中的锁问题,发现我对这方面了解太少了,像我这么热爱学习的人(其实单身狗除了写博客也没其他可做的),决定梳理一下java中的各种锁
一.
在 JDK 1.6 之前,是重量级锁 , 效率低下 。
从 JDK 1.6 开始, 做了很多优化,如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销 。
同步锁一共包含四种状态:无锁、偏向锁、轻量级锁、重量级锁,它会随着竞争情况逐渐升级 。同步锁可以升级但是不可以降级,目的是为了提高获取锁和释放锁的效率 。
的底层原理
修饰的代码块
通过反编译.class文件 , 通过查看字节码可以得到:在代码块中使用的是和指令 , 其中指令指向同步代码块的开始位置,指令指明同步代码块的结束位置 。
修饰的方法
同样查看字节码可以得到:在同步方法中会包含标记符 。该标记符指明了该方法是一个同步方法,从而执行相应的同步调用 。
二.对象锁、类锁、私有锁
对象锁:使用修饰非静态的方法以及 (this) 同步代码块使用的锁是对象锁 。
类锁:使用修饰静态的方法以及 (class) 同步代码块使用的锁是类锁 。
私有锁:在类内部声明一个私有属性如lock,在需要加锁的同步块使用 (lock)
它们的特性:

Java中各种锁的详解

文章插图
由私有锁实现的等待/通知机制
bject lock = new Object();// 由等待方线程实现synchronized (lock) {while (条件不满足) {lock.wait();}}// 由通知方线程实现synchronized (lock) {条件发生改变lock.notify();}
三.
是一个独占/排他锁 。相对于 ,它更加灵活 。但是需要自己写出加锁和解锁的过程 。它的灵活性在于它拥有很多特性 。
需要显示地进行释放锁 。特别是在程序异常时,会自动释放锁,而并不会自动释放锁,所以必须在中进行释放锁 。
它的特性:
是很多类的基?。? 内部使用的就是继承,也使用了。
四. ck
ck拥有读锁()和写锁(),读锁是一个共享锁 , 写锁是一个排他锁 。
它的特性:
五. CAS
上面提到的 、ck 都是基于(AQS),而 AQS 又是基于 CAS 。CAS 的全称是And Swap(比较与交换) , 它是一种无锁算法 。
、Lock 都采用了悲观锁的机制,而 CAS 是一种乐观锁的实现 。
CAS 的特性:
CAS 存在的问题:
六.
用于替代传统的的 wait()、() 实现线程间的协作 。
Java中各种锁的详解

文章插图
在对象中,与 wait、、 方法对应的分别是 await、 和。
必须要配合 Lock 一起使用,一个的实例必须与一个 Lock 绑定 。
它的特性:
七.
、、 都是并发工具类 。
可以指定多个线程同时访问某个资源,而和都是一次只允许一个线程访问某个资源 。由于适用于限制访问某些资源的线程数目,因此可以使用它来做限流 。
并不会实现数据的同步,数据的同步还是需要使用 、Lock 等实现 。
它的特性:
八.
可以看成是一个倒计数器,它允许一个或多个线程等待其他线程完成操作 。因此,是共享锁 。
的 () 方法将计数器减1,await() 方法会阻塞当前线程直到计数器变为0 。
九.脑图
十. 总结
本文小结了 Java 常用的一些锁及其一些特性,掌握这些锁是掌握 Java 并发编程的基础 。当然,Java 的锁并不止这些,例如的分段锁(),分布式环境下所使用的分布式锁 。
参考文章
1.Java 各种锁的小结
【Java中各种锁的详解】返回专栏目录