您的位置:首页 > 编程语言 > Java开发

深入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 -- 等两秒超时后中断放弃

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 关键字 多线程