java多线程中 synchronized 和 Lock的区别

今天复习了一点多线程的知识,顺便总结了一下synchronized和lock的区别,这两个是很重要的也很基础的知识点,这里重点只讲他们的区别。

首先lock是java.util.concurrent类库中的类的接口(lock的实现有读写锁,可重入锁,公平锁等等,我们常用的为ReentrantLock类)。其底层
为调用CAS操作(Compare And Set)实现。

一般用法为加锁时使用其
lock()(若获取了锁立即返回,若无法获取线程休眠),
tryLock()(若获取了锁立即返回true,若无法获取立即返回false),tryLock(long timeout , TimeUnit unit)(若获取了锁立即返回true,若无法获取会等待参数给定的时间,直至超时false)方法获得锁;
unlock()方法(注意一般把释放锁写到finally块中,防止死锁)释放锁,

他可以拥有一个或多个相关的条件对象(condition),由每个条件对象来管理那些已进入被保护的代码段但还不能运行的代码。
我们可以通过锁对象来获取其条件对象。

而synchronized是java里的关键字,其可以修饰方法,对象或代码块,进入synchronized代码块的线程必须获得内部对象锁,synchronized底层原理为每个对象都有一个monitor锁(类似与计算机操作系统中的管程)来实现;

只有一个相关条件,由来管理那些试图进入synchronized代码的线程,由条件来管理那些调用wait的线程。

其次,lock通过其condition对象里的await(),signalAll(),signal()方法使线程进入等待集或者从等待集唤醒。

而synchronized由Object对象里定义的wait(),notifyAll(),notify()方法使线程进入等待集或者从等待集唤醒。

另外,在资源竞争不是很激烈的情况下,synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,synchronzied的性能会下降几十倍,但是ReentrantLock的性能能维持常态。一般建议用Lock。

最后,摘取《java核心技术卷一》里的一段话:

”当一个线程试图获取一个内部对象锁(而不是java.util.concurrent库种的锁),而该锁被其他线程持有则该线程进入阻塞状态。
当线程等待另一个线程通知调度器一个条件时,他自己进入等待状态,在调用Object.wait()方法或Thread.join()方法,或者是等待java.util.concurrent库中的Lock或Condition时,就会出现这种情况。实际上被阻塞状态与等待状态是有很大不同的。”

我对这段话的理解是:只有当线程想进入synchronized保护的代码时如果没有拿到锁时,就会进入阻塞状态。

当线程想进入lock(或其condition对象)保护的代码,或者synchronize块中调用了Object.wait()方法时,才会进入等待状态。

以上,限于我的水平,若是有什么理解错误的话,请各位及时指出。

你可能感兴趣的:(java基础)