java lock condition_Java 并发:重入锁 ReentrantLock 与条件锁 Condition (上篇)

Java 并发:重入锁 ReentrantLock 与条件锁 Condition (上篇)

这篇文章的起因,是因为最近有很多小伙伴表示,面试时候被问到了很多关于Java并发的问题,尤其是在Java的锁方面,大部分人工作时候接触的只有synchronized,对于Java中其它形式的锁几乎一无所知。

这个责任其实主要在于一些老程序员。像重入锁是在Java 1.5以后才支持的,但很多教材和陈年老代码,却仍然坚持着使用synchronized,并不试图去研究一些新的特性——我知道很多人会用奥卡姆剃刀原则反驳我,即“如无必要,勿增实体”,可惜的是很多时候,对于”如无必要“的判断都是值得商榷的。所以我今天想介绍一下在Java并发中,我个人比较推崇的这种可以替代synchronized的工具类。

另外,我会尽量尝试用任何人都听得懂的表述形式。

需要注意的是,得益于Java不断的发展,目前synchronized关键字和ReentrantLock类的性能差异,已经少之又少了。但是我个人认为,在代码可读性与灵活性方面,ReentrantLock还是稍胜一筹。

Why ReentrantLock?

像上面说的一样,80%的场景下,synchronized关键字可以和ReentrantLock相互替换,实现同样的功能,并且性能相差无几。但对于一些特殊的case,ReetrantLock就灵活多了。

1)synchronized实现是非公平锁的实现,而ReentrantLock可以指定公平锁或者非公平锁。

这里简单介绍一下其间的差别。大家都知道,实际上并发线程,并不一定是并行执行的,很多情况下并发的线程是由CPU分配时间片,实际上有可能是串行的,只是由于CPU分配的关系,看起来像并行执行而已。那么对于多个线程申请同一个带锁的资源,CPU要怎么分配呢?

这就取决于锁的性质了。对于公平锁而言,系统会维护一个有序队列,几乎是严格遵守”先来后到“原则,按照时间顺序分配资源。对于非公平锁,基本上就是随机挑选,所以可以产生各种插队的情况。当然,实际实现要更加复杂,但中心思想就是这样。

由于要维护执行队列,公平锁性能会远低于非公平锁,但公平锁的行为是可预测行为,在某些特定环境下公平要比效率更重要一些。

举个例子:

public class FairLock extends Thread {

public static ReentrantLock fair = new ReentrantLock(true); // true表示公平锁

public FairLock(String s) {

super(s);

}

@Override

public void run() {

while (true) {

try {

fair.lock();

System.out.println(Thread.currentThread()

.getName() + " is running");

} finally {

fair.unlock();//必须在finally里释放锁

}

}

}

public static void main(String args[]) throws InterruptedException {

new FairLock("wtf 1").start();

new FairLock("wtf 2").start();

}

}

上述代码中两个FairLock的实例都在申请同一个重入锁,但控制台打印就类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值