JAVA并发-显式锁(二)

在上一篇博客 《JAVA并发-显式锁(一)》中介绍了Lock和ReadWriteLock的基本用法,下面来看看如何使用Lock的tryLock()方法来避免死锁。
在博客 《JAVA并发-3种典型的死锁》中有一个动态的锁顺序死锁。我们使用System.identifyHashCode()来固定线程获取锁的顺序,从而解决了死锁问题。学习了Lock之后,可以使用tryLock()来解决动态的锁顺序死锁问题。代码如下:
class Test {
    public boolean transfer(Account from,Account to,int num,long timeout,TimeUnit unit){
    	long endTime=System.nanoTime()+unit.toNanos(timeout);
    	while(endTime>System.nanoTime()){
    		if(from.lock.tryLock()){
    			try{
    				if(to.lock.tryLock()){
    					try{
    						//转账操作
    						return true;
    					}finally{
    						to.lock.unlock();
    					}
    				}
    			}finally{
    				from.lock.unlock();
    			}
    		}
    	}
    	return false;
    }
}
class Account{
	public Lock lock=new ReentrantLock();
	//...
}

可以看到,我们 使用tryLock实现了轮循锁和定时锁。tryLock会尝试获得2个锁,如果不能同时获得,那就释放已获得的锁然后重试。如果在指定的时间内不能获得所有锁,那就返回一个失败的状态。

下面介绍下与锁相关的几个概念:
1. 可重入锁:什么叫可重入锁呢?如下例子:当一个线程持有锁并执行fun1方法时,他不再需要重新申请该对象锁来执行fun2方法(实际上,如果需要重信申请的话,就死锁了),此时我们说synchronized是可重入的。实际上,synchronized和ReentrantLock都是可重入的锁。
可重入锁说明,锁的分配机制是基于线程的,而不是基于方法的。
class Test {
    public synchronized void fun1(){
    	fun2();
    }
    public synchronized void fun2(){
    	//doSomething
    }
}


2. 可中断锁:可以响应中断的锁,当一个线程正在等待锁时,可以响应中断。synchronized是不可中断锁,而Lock是可中断锁。

3. 公平锁:能够保证以请求锁的顺序来获得锁,就是公平锁。否则,就是非公平锁。我们希望做到公平,但实际应用中非公平锁的性能更好。在Java中,synchronized是非公平锁,它无法保证等待的线程获取锁的顺序。对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。



笔者开设了一个知乎live,详细的介绍的JAVA从入门到精通该如何学,学什么?

提供给想深入学习和提高JAVA能力的同学,欢迎收听https://www.zhihu.com/lives/932192204248682496


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值