Java lock free queue 구현을 작성했습니다. 동시성 버그가 있습니다. 못 찾겠 어. 이 코드는 중요하지 않습니다. 휘발성 변수와 관련된 관찰 된 동작을 설명 할 수 없다는 것에 대해 걱정할뿐입니다.잠금 해제 대기열에 버그가 어디 있습니까?
버그는 예외 ("null head")로 볼 수 있습니다. 현재 큐 크기를 유지하는 원자 적 정수가 있기 때문에 불가능한 상태입니다. 큐에는 스텁 요소가 있습니다. 독자 스레드는 테일 포인터를 변경하지 않고 작성자 스레드는 헤드 포인터를 변경하지 않습니다.
대기열 길이 변수는 링크 된 목록이 절대로 비어 있지 않음을 보장합니다. 그것은 세마포어입니다.
take 메소드는 길이 값을 도난당한 것처럼 동작합니다.
class Node<T> {
final AtomicReference<Node<T>> next = new AtomicReference<Node<T>>();
final T ref;
Node(T ref) {
this.ref = ref;
}
}
public class LockFreeQueue<T> {
private final AtomicInteger length = new AtomicInteger(1);
private final Node stub = new Node(null);
private final AtomicReference<Node<T>> head = new AtomicReference<Node<T>>(stub);
private final AtomicReference<Node<T>> tail = new AtomicReference<Node<T>>(stub);
public void add(T x) {
addNode(new Node<T>(x));
length.incrementAndGet();
}
public T takeOrNull() {
while (true) {
int l = length.get();
if (l == 1) {
return null;
}
if (length.compareAndSet(l, l - 1)) {
break;
}
}
while (true) {
Node<T> r = head.get();
if (r == null) {
throw new IllegalStateException("null head");
}
if (head.compareAndSet(r, r.next.get())) {
if (r == stub) {
stub.next.set(null);
addNode(stub);
} else {
return r.ref;
}
}
}
}
private void addNode(Node<T> n) {
Node<T> t;
while (true) {
t = tail.get();
if (tail.compareAndSet(t, n)) {
break;
}
}
if (t.next.compareAndSet(null, n)) {
return;
}
throw new IllegalStateException("bad tail next");
}
}
잠금 메커니즘이 사용되지 않을 때이 코드는 데이터 경합을 어떻게 방지합니까? 왜 당신은 자물쇠를 사용하고 싶지 않아? – Chriss
언제 문제가 발생합니까? 당신은 문제를보기 전에 하나의 리더 쓰레드로 얻을 수 있습니까? 아니면 여러 독자가 필요합니까? takeOrNull의 두 번째 루프에있는 여러 리더 스레드 주위에 문제가 있다고 생각됩니다. –
이것은 프로덕션 코드가 아닙니다. 이것을 운동으로 간주하십시오. –