AtomicBoolean 提供了一种原子性读写布尔类型变量的解决方案,通常情况下,该类用于原子性的更新状态标识位,如 flag ---- 《java 高并发编程详解》
今天主要介绍如何使用 AtomicBoolean来实现一个常见显示锁,用来替代同步操作synchronized, 通常来说synchronized的代价是比较高的,会使线程在争夺对象监视器的时候进入 阻塞状态。而本文将借助AtomicBoolean实现一个可以立刻返回并且退出阻塞状态的显示锁 TryLock。
以下是代码:
package com.asqhaqs.atomicity;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 使用 AtomicBoolean 实现一个 显示锁
*/
public class TryLock {
private final AtomicBoolean ab = new AtomicBoolean(false);
// 线程保险箱,用于存放与线程上下文相关联的数据副本,确保只有获取锁的线程才能释放锁
private final ThreadLocal<Boolean> threadLocal = ThreadLocal.withInitial(()->false);
public boolean tryLock() {
//只有在未加锁时候(false)才能正确设置
boolean result = ab.compareAndSet(false, true);
if (result) {
threadLocal.set(true);
}
return result;
}
public boolean release() {
// 只有成功获取锁的线程才能释放锁
if (threadLocal.get()) {
threadLocal.set(false);
return ab.compareAndSet(true, false);
} else {
return false;
}
}
}
以下是该锁的使用代码:
package com.asqhaqs.atomicity;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.ThreadLocalRandom.current;
import static java.lang.Thread.currentThread;
public class TryLockExample {
private final static Object VAL_OBJ = new Object();
public static void main(String[] args) {
final TryLock lock = new TryLock();
final List<Object> validation = new ArrayList<>();
// 启动10个线程, 并且不断进行锁的获取以及释放操作
for(int i = 0; i < 10; i++) {
new Thread( () -> {
while (true) {
try {
// 尝试获取锁, 该方法不会导致当前线程进入阻塞
if (lock.tryLock()){
System.out.println(currentThread() + ": get the lock.");
if (validation.size() > 1){
throw new IllegalAccessException("validation failed. ");
}
validation.add(VAL_OBJ);
TimeUnit.MILLISECONDS.sleep(current().nextInt(10));
}else {
// 如果没有获取锁, 做个休眠,防止死机
TimeUnit.MILLISECONDS.sleep(current().nextInt(10));
}
} catch (InterruptedException | IllegalAccessException e) {
e.printStackTrace();
} finally {
// 释放锁
if (lock.release()){
System.out.println(currentThread() + ": release the lock.");
validation.remove(VAL_OBJ);
}
}
}
}).start();
}
}
}
执行结果