package com.wang.lock;
public class QNode {
volatile boolean locked;
}
package com.wang.lock;
public interface Lock {
void lock();
void unlock();
}
package com.wang.lock;
import java.util.concurrent.atomic.AtomicReference;
public class CLHLock implements Lock {
private final AtomicReference<QNode> tail;
private final ThreadLocal<QNode> myPred;
private final ThreadLocal<QNode> myNode;
public CLHLock() {
tail = new AtomicReference<QNode>(new QNode());
myNode = new ThreadLocal<QNode>() {
protected QNode initialValue() {
return new QNode();
}
};
myPred = new ThreadLocal<QNode>();
}
@Override
public void lock() {
QNode node = myNode.get();
node.locked = true;
QNode pred = tail.getAndSet(node);
myPred.set(pred);
while (pred.locked) {
}
}
@Override
public void unlock() {
QNode node = myNode.get();
node.locked = false;
myNode.set(myPred.get());
}
}
package com.wang.lock;
import java.util.ArrayList;
import java.util.List;
public class CLHMain {
public static void main(String[] args) throws Exception {
test1();
}
private static void test1() throws Exception {
final Lock lock = new CLHLock();
Runnable r = new Runnable() {
public void run() {
lock.lock();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
}
lock.unlock();
}
};
List<Thread> list = new ArrayList<>();
for (int i = 0; i < 4; i++) {
list.add(new Thread(r));
}
for (Thread t : list) {
t.start();
}
}
}
/*
eg:Thread1 Thread2
1. t1.lock: tail.node=t1.node, t1.lock=true, t1.pred=nullNode
2. t2.lock: tail.node=t2.node, t2.lock=true, t2.pred=t1.node , t1.node.lock=true, t2 while(t1.node.lock)
3. t1.unlock tail.node=t2.node, t1.lock=false,t1.node=t1.pred=nullNode,
4. t2.unlock tail.node=t2.node, t2.lock=false,t2.node=t1.node
5. t1.lock tail.node=t1.node=NullNode,t1.node=true,t1.pred=t2.node;
*/