模拟的场景是这样的:
在分布式环境中,使用redis分布式锁,当一个线程获取分布式锁后,其他线程不使用自旋,而是直接进入阻塞状态。已知的方式是可以使用redisson实现阻塞等待的情况。但是博主只是想模拟一下没用redisson的话是否可以通过单机的锁实现阻塞,减少线程对资源的消耗。
思路:
模拟获取锁失败,则获取map的锁,然后new一个CountDownLatch放入map中,然后开启一个线程传入CountDownLatch,查询是否释放了锁,如果完成更新则调用countdown()方法。主线程将CountDownLatch锁放入map中,调用await()方法进入等待。
其他线程获取锁失败,先查询map中是否已经存在CountDownLatch锁了,如果存在,则使用该锁,进入await();
上代码:
public class CountDownLatchTest {
public HashMap<String, CountDownLatch> lock = new HashMap<String, CountDownLatch>();
public void lock() {
CountDownLatch countDownLatch = lock.get("lock");
if (null == countDownLatch) {
synchronized (lock) {
countDownLatch = lock.get("lock");
if (null == countDownLatch) {
System.out.println("不存在锁!");
countDownLatch = new CountDownLatch(1);
lock.put("lock", countDownLatch);
final CountDownLatch cd2 = countDownLatch;
// 开启一个异步线程去查询
new Thread() {
public void run() {
try {
//模拟查询是否释放了锁
Thread.sleep(5000);
//解锁
System.out.println("开始解锁!");
cd2.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
} else {
System.out.println("存在锁2!");
}
}
} else {
System.out.println("存在锁1!");
}
try {
countDownLatch.await();
System.out.println("开始执行业务!");
//删除缓存
lock.remove("lock");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
final CountDownLatchTest countDownLatchTest = new CountDownLatchTest();
for(int i = 0; i < 5; i++) {
new Thread() {
public void run() {
countDownLatchTest.lock();
}
}.start();
}
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < 5; i++) {
new Thread() {
public void run() {
countDownLatchTest.lock();
}
}.start();
}
}
}
结果:
第一次写文章,请轻喷~