总结
类别 | synchronized | Lock |
---|---|---|
存在层次 | Java的关键字,在jvm层面上 | 是一个类 |
锁的释放 |
1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁 |
在finally中必须释放锁,不然容易造成线程死锁 |
锁的获取 | 假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待 | Lock 可以设置尝试获取锁或者获取锁一定时间超时后失败 |
锁状态 | 无法判断 | 可以判断 |
控制等待和唤醒 | 结合加锁对象的 wait() 和 notify()、notifyAll() | 结合 Condition 的 await() 和 signal()、signalAll() 方法 |
锁类型 | 可重入 不可中断 非公平 | 可重入 可判断 可公平/非公平(两者皆可,构造函数参数控制) |
性能 | 少量同步 | 大量同步 |
ref: https://blog.csdn.net/qq_39521554/article/details/81130442
为什么有了synchronized,还需要Lock?
二者都是可重入锁,那么为什么要有两个呢?既然存在,那么就一定是有意义的。synchronized是Java中的一个关键字,而Lock是Java1.5后在java.util.concurrent.locks包下提供的一种实现同步的方法,那么显然的,synchronized一定是有什么做不到的或者缺陷,才导致了Lock的诞生。
synchronized的缺点
1)当一个代码块被synchronized修饰的时候,一个线程获取到了锁,并且执行代码块,那么其他的线程需要等待正在使用的线程释放掉这个锁,那么释放锁的方法只有两种,一种是代码执行完毕自动释放,一种是发生异常以后jvm会让线程去释放锁。那么如果这个正在执行的线程遇到什么问题,比如等待IO或者调用sleep方法等等被阻塞了,无法释放锁,而这时候其他线程只能一直等待,将会特别影响效率。那么有没有一种办法让其他线程不必一直傻乎乎的等在这里吗?
2)当一个文件,同时被多个线程操作时,读操作和写操作会发生冲突,写操作和写操作会发生冲突,而读操作和读操作并不会冲突,但是如果我们用synchronized的话,会导致一个线程在读的时候,其他线程想要读的话只能等待,那么有什么办法能不锁读操作吗?
3)在使用synchronized时,我们无法得知线程是否成功获取到锁,那么有什么办法能知道是否获取到锁吗?有,Lock接口
Lock的使用和原理
使用实例:https://www.cnblogs.com/huangbw/p/8516024.html
原理分析:https://blog.csdn.net/michaelgo/article/details/81481068