표준 union/find or Disjoint-set 데이터 구조는 단일 스레드 케이스에 대해 매우 좋은 실행 시간 (효과적으로 O(1)
)을가집니다. 멀티 스레드 케이스에서 유효성/성능은 무엇입니까? I 은 원자 포인터 크기의 쓰기를 제외하고는 잠금 또는 원자 연산이 없이도 완전히 유효하다고 생각합니다.일반 노동 조합/찾기 알고리즘 스레드가 추가 작업없이 안전합니까?
누구나 다음과 같은 논리에 문제가 있습니까?
우선 포인터 크기의 쓰기는 원자 적이라고 가정합니다. 그로 인해 발생하는 유일한 업데이트가 모두 같은 값으로 설정되므로 안전하게 여러 스레드에서
find
함수를 실행할 수 있다고 주장하는 것이 어렵지 않습니다.find
함수가 호출되었을 때 true를 반환하도록 허용하면 (반환되었을 때와 반대) 많은find
과 하나의union
이 동시에 실행될 수 있다고 주장하는 것이 어렵지 않습니다.find
에 대한 인수는 변경되지 않으며union
은 뿌리만을 업데이트하고find
은 뿌리를 업데이트하지 않습니다.나머지 사례 (여러
union
초)에 대해서는 잘 작동하지만 잘 모르겠습니다.
BTW : 솔루션이 단일 스레드 버전만큼 효율적일 필요는 없습니다. (/ 원자 잠금을 방지하기 위해, 또한 전 세계적으로 일관된 상태를 폐기 할 용입니다.)
이 편집 : 다른 모양을 가지고, 많은 노조의 경우는 작동하지 않기 때문에 경우 측면이 새 루트가 다른 루트와 결합되지 않았 으면 (루트가 아닌) 두 번째 조합의 다른 쪽에서 잘라낼 수 있습니다.
A = find(a) // union 1
B = find(b) // union 1
----
X = find(x) // union 2 (x == a) -> (X == A) -> (X.par aliases A.par)
Y = find(y) // union 2
X.par = Y // union 2
----
A.par = B // union 1
이
는 CAS으로 한 발짝 비켜 될 수있다 :이 구조에 사용할 수있는 동기화while(!CAS(A == A.par, B)) A = find(A);
, 당신이 언급하는 비 원자 노조 것은 순위 일부인 경우 A와 B – Dave