锁的可重入性(Reentrant)

1. 可重入锁的定义

public synchronized void test(){ 
    //business 
    test1(); 
}
 
public synchronized void test1(){ 
    //business 
}

在上段代码中,执行test方法需要获取当前对象的监视器锁,而test方法内部又调用了同步方法test1。

如果对象监视器锁是具有可重入性的,那么该线程在调用test1时,可以再次或的对象的监视器锁,从而进入test1方法。

如果对象监视器锁不具有可重入性,那么线程在test方法中调用同步方法test1之前,需要等待当前对象监视器锁的释放,然而,实际上该对象的监视器锁已经被当前线程所持有,不可能再次获得,死锁产生。

综上,锁的可重入性就是一个线程在已经持有锁的情况下,能否再次获取这把锁。

所以,如果有方法的递归调用发生,方法中的锁必须是可重入锁,否则会造成死锁的发生。

BTW,对象监视器锁是可重入锁,所以上面的代码能够正产执行。

 

2. 可重入锁的使用

同一个可重入锁,被同一线程锁了几次,就需要释放几次。

a) Synchronized修饰的对象监视器锁,在临界区(同步块/同步方法)自动锁定和解锁。

b) ReentrantLock这种显式锁,需要手动释放。

		if(reentrantLock.tryLock()){
			String currentThreadName = Thread.currentThread().getName();
			try {
				System.out.println(currentThreadName + " get reentrantLock....");
				Thread.sleep(100);
			} catch (InterruptedException e) {
				System.out.println(currentThreadName + " is interrupted....");
			} finally{
				System.out.println(currentThreadName + " release reentrantLock....");
				reentrantLock.unlock();
			}
		}else{
			System.out.println(Thread.currentThread().getName() + " is waiting for lock release....");
			this.reentrantLock.lock();
			this.run();//do the business
			System.out.println(Thread.currentThread().getName() + " release reentrantLock");
			this.reentrantLock.unlock();//when using ReentrantLock, recursion lock need recursion unlock
		}

 

转载于:https://my.oschina.net/mose/blog/681969

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis分布式的实现主要包含以下步骤: 1. 获取:使用Redis的SETNX命令尝试获取,如果返回1表示获取成功,否则表示已被占用。 2. 设置超时时间:为了防止死,需要为设置一个超时时间,可以使用Redis的EXPIRE命令设置的过期时间。 3. 释放:使用Redis的DEL命令删除。 4. 重入性:为了支持重入性,我们可以在的value中保存一个计数器,每次获取时计数器加1,释放时计数器减1,当计数器为0时才真正释放。 5. 重试性:如果获取失败,可以使用重试机制尝试重新获取,比如可以使用while循环不断尝试获取,直到获取成功或达到最大重试次数。 以下是一个示例代码实现: ```python import redis import time class RedisLock: def __init__(self, redis_client, key, expire=30, retry=3): self.redis_client = redis_client self.key = key self.expire = expire self.retry = retry self.reentrant = False self.reentrant_count = 0 def acquire(self): while self.retry > 0: result = self.redis_client.setnx(self.key, 1) if result: self.redis_client.expire(self.key, self.expire) self.reentrant = True self.reentrant_count = 1 return True else: if self.redis_client.ttl(self.key) == -1: self.redis_client.expire(self.key, self.expire) if self.reentrant and self.redis_client.get(self.key) == 1: self.reentrant_count += 1 return True self.retry -= 1 time.sleep(1) return False def release(self): if self.reentrant and self.reentrant_count > 1: self.reentrant_count -= 1 return True elif self.reentrant and self.reentrant_count == 1: self.redis_client.delete(self.key) self.reentrant = False self.reentrant_count = 0 return True else: self.redis_client.delete(self.key) return True ``` 在这个示例中,我们使用了一个RedisLock类来封装了Redis分布式的实现。其中,acquire方法尝试获取,如果获取成功则返回True,否则返回False;release方法释放。在acquire方法中,我们使用了while循环和retry机制来不断尝试获取,如果获取成功则设置的过期时间,并且为了支持重入性,设置了reentrant和reentrant_count变量。在release方法中,如果reentrant为真且reentrant_count大于1,则表示是重入的释放操作,只需要将reentrant_count减1即可;如果reentrant为真且reentrant_count等于1,则表示真正的释放操作,需要将从Redis中删除,并将reentrant和reentrant_count变量重置为False和0。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值