其他分享
首页 > 其他分享> > ReentrantLock与synchronized的区别

ReentrantLock与synchronized的区别

作者:互联网

Synchronized

Synchronized 是通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本质又是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么 Synchronized 效率低的原因。因此,这种依赖于操作系统 Mutex Lock 所实现的锁我们称之为 “重量级锁”

同步方法通过ACC_SYNCHRONIZED 关键字隐式的对方法进行加锁。当线程要执行的方法被标注上ACC_SYNCHRONIZED时,需要先获得锁才能执行该方法。
同步代码块通过monitorenter和monitorexit执行来进行加锁。当线程执行到monitorenter的时候要先获得锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。每个对象自身维护着一个被加锁次数的计数器,当计数器不为0时,只有获得锁的线程才能再次获得锁。

ReentrantLock

ReentrantLock通过原子操作和阻塞实现锁原理,一般使用lock获取锁,unlock释放锁

lock的时候可能被其他线程获得所,那么此线程会阻塞自己,关键原理底层用到Unsafe类的API: CAS和park

ReentantLock 继承接口Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完
成synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等
避免多线程死锁的方法。

 

Lock 主要方法
1. void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经
被其他线程持有, 将禁用当前线程, 直到当前线程获取到锁.
2. boolean tryLock():如果锁可用, 则获取锁, 并立即返回true, 否则返回false. 该方法和
lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被禁用,
当前线程仍然继续往下执行代码. 而lock()方法则是一定要获取到锁, 如果锁不可用, 就一
直等待, 在未获得锁之前,当前线程并不继续向下执行.
3. void unlock():执行此方法时, 当前线程将释放持有的锁. 锁只能由持有者释放, 如果线程
并不持有锁, 却执行该方法, 可能导致异常的发生.
4. Condition newCondition():条件对象,获取等待通知组件。该组件和当前的锁绑定,
当前线程只有获取了锁,才能调用该组件的await()方法,而调用后,当前线程将缩放锁。

ReentrantLock 与 synchronized

1.ReentrantLock 通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized 会
被JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出
现异常而无法正常解锁的情况,使用ReentrantLock 必须在finally 控制块中进行解锁操
作。
2. ReentrantLock 相比synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要
使用ReentrantLock。

 

wait() notify() notifyAll() 和await() signal() 和 signalAll() 的区别?

在使⽤Lock之前,我们都使⽤Object+的wait和notify实现同步。

Synchronized(obj){

obj.wait://此时这个线程会释放锁。并等待其他线程唤醒才能往下执行。

}

Synchronized(obj){

obj.notify://此时这个线程会释放锁。并等待其他线程唤醒才能往下执行。

}

而Lock则是由Lock控制锁,Condition来控制被阻塞线程

// 消费者
lock.lock();

condition.await();
lock.unlock();


//生产者
lock.lock();
condition.signal();
lock.unlock();

为了突出区别,省略了若⼲细节。区别有三点:

1.lock不再使用synchronize把同步代码包装起来

2.阻塞需要另外一个对象condition。

3.对应的方法是await和signal。

使用lock的好处就是我们可以指定条件来唤醒某个线程。而object 的唤醒是随机的

假设我们我们的需要想让a线程执行。

Lock lock = new ReentrantLock();

Condition acondition=lock.newCondition();//创建Condition

Condition bcondition=lock.newCondition();//创建Condition

可以acondition.signal().这样a线程就可以唤醒了。

 

标签:synchronized,区别,lock,ReentrantLock,线程,Lock,执行,方法
来源: https://www.cnblogs.com/wmdshijie/p/16319706.html