深入Java多线程和并发编程之ReentrantLock
2016-12-07 17:50
375 查看
ReentrantLock可以等同于synchronized使用、但是它比synchronized有更强的功能、可以提供更灵活的锁机制、同时减少死锁的发生概率。我们平时用用synchronized也就够了、但是要写好一个复杂的多线程系统、为了提供更灵活的同步机制、就需要用到ReentrantLock了。
ReentrantLock相比synchronized多了以下一些特性:
1、synchronized关键字只能支持单条件(condition)、比如10个线程都在等待synchronized块锁定的资源、如果一直锁定、则其他线程都得不到释放从而引起死锁;而同样的情况使用ReentrantLock、则允许其他线程中断放弃尝试。reentrantlock本身支持多wait/notify队列、它可以指定notify某个线程。
对中断的支持代码:
Java代码
public final void acquireInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
2、ReentrantLock可以成为公平锁、所谓公平锁就是让等待最长的线程最早获得该锁(获得锁的顺序和申请锁的顺序是一致的);与之对应的synchronized是非公平的、当然ReentrantLock也可以成为非公平锁;只是公平锁的性能相对差一些。
Java代码
public ReentrantLock(boolean fair) {
sync = (fair)? new FairSync() : new NonfairSync();
}
3、ReentrantLock又叫可重入锁、也就是说一个线程拥有锁了之后可以再次确认是否持有锁而不会出现死锁的问题。
4、ReentrantLock可以获取有多少线程正在等待该锁
以上几个特点使ReentrantLock相比synchronized的锁粒度更细、使用起来更灵活、可以满足更多的功能。
下面是ReentrantLock的一个代码示例:
Java代码
//: concurrency/AttemptLocking.java
// 以下是ReentrantLock中断机制的一个代码实现、如果换成synchronized就会出现死锁
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed() {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): " + captured);
} finally {
if (captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
} finally {
if (captured)
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
final AttemptLocking al = new AttemptLocking();
al.untimed(); // True -- 可以成功获得锁
al.timed(); // True --可以成功获得锁
//新创建一个线程获得锁并且不释放
new Thread() {
{
setDaemon(true);
}
public void run() {
al.lock.lock();
System.out.println("acquired");
}
}.start();
Thread.sleep(100);// 保证新线程能够先执行
al.untimed(); // False -- 马上中断放弃
al.timed(); // False -- 等两秒超时后中断放弃
}
}
ReentrantLock相比synchronized多了以下一些特性:
1、synchronized关键字只能支持单条件(condition)、比如10个线程都在等待synchronized块锁定的资源、如果一直锁定、则其他线程都得不到释放从而引起死锁;而同样的情况使用ReentrantLock、则允许其他线程中断放弃尝试。reentrantlock本身支持多wait/notify队列、它可以指定notify某个线程。
对中断的支持代码:
Java代码
public final void acquireInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
2、ReentrantLock可以成为公平锁、所谓公平锁就是让等待最长的线程最早获得该锁(获得锁的顺序和申请锁的顺序是一致的);与之对应的synchronized是非公平的、当然ReentrantLock也可以成为非公平锁;只是公平锁的性能相对差一些。
Java代码
public ReentrantLock(boolean fair) {
sync = (fair)? new FairSync() : new NonfairSync();
}
3、ReentrantLock又叫可重入锁、也就是说一个线程拥有锁了之后可以再次确认是否持有锁而不会出现死锁的问题。
4、ReentrantLock可以获取有多少线程正在等待该锁
以上几个特点使ReentrantLock相比synchronized的锁粒度更细、使用起来更灵活、可以满足更多的功能。
下面是ReentrantLock的一个代码示例:
Java代码
//: concurrency/AttemptLocking.java
// 以下是ReentrantLock中断机制的一个代码实现、如果换成synchronized就会出现死锁
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed() {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): " + captured);
} finally {
if (captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
} finally {
if (captured)
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
final AttemptLocking al = new AttemptLocking();
al.untimed(); // True -- 可以成功获得锁
al.timed(); // True --可以成功获得锁
//新创建一个线程获得锁并且不释放
new Thread() {
{
setDaemon(true);
}
public void run() {
al.lock.lock();
System.out.println("acquired");
}
}.start();
Thread.sleep(100);// 保证新线程能够先执行
al.untimed(); // False -- 马上中断放弃
al.timed(); // False -- 等两秒超时后中断放弃
}
}
相关文章推荐
- 【Java并发编程】15、ReentrantLock实现原理深入探究
- java并发编程之:ReentrantLock实现原理与深入研究
- Java 多线程并发编程之互斥锁 Reentrant Lock
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
- JAVA并发编程学习笔记之ReentrantLock
- java多线程编程——显示锁ReentrantLock(一)
- JAVA并发编程学习笔记之ReentrantLock
- 【多线程】Java并发编程:Lock(转载)
- 深入学习java并发编程:Lock与AbstractQueuedSynchronizer(AQS)实现
- 并发编程学习总结(四) :java 显式锁ReentrantLock使用详解之lock()\unlock() 加锁与释放锁
- 并发编程学习总结(六) :java 显式锁ReentrantLock使用详解之测试锁与超时
- Java并发编程之显示锁ReentrantLock和ReadWriteLock读写锁
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
- Java多线程编程--(7)学习Java5.0 并发编程包--Lock & Condition
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
- java多线程:并发包中ReentrantLock锁的公平锁原理
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
- 【Java并发编程实战】—–“J.U.C”:ReentrantReadWriteLock
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之二lock方法分析