aqs中使用的FIFO队列是clh自旋锁的一个变种,所以理解clh对理解aqs很有帮助。
自旋锁适合于加锁时间短的任务,一直忙等。互斥锁适合加锁时间长的任务,需要wait,notify。
附上clh自旋锁java实现。
public class CLHLock {
private class Node {
private volatile boolean locked;
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
}
private final ThreadLocal<Node> prev = ThreadLocal.withInitial(() -> null);
private final ThreadLocal<Node> current = ThreadLocal.withInitial(Node::new);
private final AtomicReference<Node> tail = new AtomicReference<>(new Node());
public void lock(){
Node node = this.current.get();
node.setLocked(true);
Node pred = tail.getAndSet(node);
this.prev.set(pred);
while(this.prev.get().isLocked()){
}
}
public void unlock(){
Node node = this.current.get();
node.setLocked(false);
this.current.set(this.prev.get());
}
public static void main(String[] args) {
CLHLock clhLock = new CLHLock();
for(int i = 0; i < 10; i++){
new Thread(() -> {
clhLock.lock();
System.out.println(Thread.currentThread().getName() + "获取锁");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
clhLock.unlock();
}
}, "线程" + i).start();
}
}
}