JAVAロック---------CLHロックとMCSロック
参考:http://ifeve.com/java_ロックsee 2/
一:CLHロック実装 CLHロックは、前駆変数preNodeを継続的に照会することによって実現され、暗黙的なキューであり、真の後継ノード は存在しない。 lock関数は、lockを呼び出すときに、まず自分のtail nodeノードを新たに作成し、自分のスレッドスタックに共存して、共有のtail nodeをudaterで取得し、共有のtail nodeを自分のtail nodeに更新し、共有のtail nodeが空でない場合は、ロックを取得し失敗し、空ポーリングを実行します。 unlock関数が実装され、現在のスレッドのtail nodeノードを取り出し、共有されているtail nodeノードと比較し、同じであればロックを解除し、同時に共有されているtail nodeをnull に更新する。 CLHロックも公平ロックであり、先着順に従っていますが、他のスピンロックと同様、競争が激しくなると性能が低下します。
二:MCSロック 実装 によって実現され、またCLHロックに加えて、実質的な後継ノード が追加されている。 CLHlockは、前駆変数を継続的に照会し、NUMAアーキテクチャで使用することに不適切をもたらす(このような構造では、各スレッドは異なる物理メモリ領域に分布し、MCSLockはローカル変数のノードを循環する。CLHlockの問題は存在しません。
一:CLHロック
package com.eden.coreLearn.thread.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import org.junit.Test;
/**
* CLH
*
* @author [email protected] 2016 7 15 5:39:38
*/
public class CLHLock {
public static class CLHNode {
private volatile boolean isLocked = true;
}
@SuppressWarnings("unused")
private volatile CLHNode tail;
private static final ThreadLocal nodeLocal = new ThreadLocal();
// CLHLock tail, CLHNode ( volatile )
private static final AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater
.newUpdater(CLHLock.class, CLHNode.class, "tail");
public void lock() {
CLHNode node = new CLHNode();
nodeLocal.set(node);
CLHNode preNode = updater.getAndSet(this, node);
// System.out.println(String.format("preNode=%s", preNode));
if (preNode != null) {
while (preNode.isLocked) {
}
preNode = null;
nodeLocal.set(node);// set
}
}
public void unlock() {
CLHNode node = nodeLocal.get();//
if (!updater.compareAndSet(this, node, null)) {
node.isLocked = false;
}
node = null;
}
@Test
public void testCLHLock() throws InterruptedException {
Student st = new Student(new CLHLock());
for (int i = 0; i < 100; i++) {
new Thread(new CLHLockThread(st), i + "").start();
}
TimeUnit.SECONDS.sleep(30);
}
public class Student {
private int i = 0;
private CLHLock lock;
public Student(CLHLock lock) {
this.lock = lock;
}
public void add() {
lock.lock();
this.i = this.i + 1;
System.out.println(String.format(" %s i=%s", Thread.currentThread().getName(), this.i));
// lock.unlock();
}
}
public class CLHLockThread extends Thread {
private Student st;
public CLHLockThread(Student st) {
this.st = st;
}
@Override
public void run() {
st.add();
}
}
}
二:MCSロック
package com.eden.coreLearn.thread.lock;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
/**
*
* @author [email protected] 2016 7 15 6:36:40
*/
public class MCSLock {
public class MCSNode {
private volatile MCSNode next;
private volatile boolean isLocked = true;
}
private static final ThreadLocal nodeLocal = new ThreadLocal();
@SuppressWarnings("unused")
private volatile MCSNode node;
private static final AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater
.newUpdater(MCSLock.class, MCSNode.class, "node");
public void lock() {
MCSNode current = new MCSNode();
nodeLocal.set(current);
MCSNode preNode = updater.getAndSet(this, current);
if (preNode != null) {
preNode.next = current;
while (current.isLocked) {
}
}
}
public void unlock() {
MCSNode current = nodeLocal.get();
if (current.next == null) {
if (updater.compareAndSet(this, current, null)) {
} else {
while (current.next == null) {
}
}
} else {
current.next.isLocked = false;
current.next = null;
}
}
}