나는 lock-free singlely linked list를 구현하는 방법을 생각 해왔다. 그리고 솔직히 말해서, 나는 그것을하는 많은 총알 증명 방법을 보지 못합니다. 밖에 나가는 을 사용하는 더 튼튼한 방법은 결국 어느 정도의 ABA problem을가집니다.이 test_and_set 스레드 사용은 안전합니까?
그래서 생각하고 있습니다. 부분적으로 자물쇠가없는 시스템이 항상 자물쇠를 사용하는 것보다 낫지 않습니까? 일부 작업은 원자 적이며 잠금이 해제 될 수 있습니까? 그렇게 할 수 있다면 여전히 스레드로부터 안전해야합니다.
그래서, 질문에. 나는 단순하게 연결된 목록을 생각하고있다. 2 가지 주요 작업. push
및 pop
. push
은 항상 앞쪽에 삽입합니다. 이 같은 것 :
void push(int n) {
T *p = new T;
p->n = n;
p->next = root;
root = p;
}
항상 첫 번째 요소를 취하는 pop. 이런 식으로 :
T *pop() {
T *p = root;
root = root->next;
return p;
}
분명히 간단하게 잠글 수는 없으므로 잠금이 필요하지 않습니다. 그러나 대중 음악은 아마도 가능할 것 같습니다. gcc-intrinsics를 사용하여 다음과 같이 생각했습니다.
T *pop() {
return __sync_lock_test_and_set(&root, root->next);
}
기능상으로 동일합니까? 예. 자물쇠가 없습니까? 예. 쓰레드 안전? 잘 모르겠 음. 내 직감 반증은 아니오이며, 여기에 이유가 있습니다.
test_and_set
에 대한 매개 변수 중 하나가 메모리를 비 참조 화해야한다는 사실에 대해 우려하고 있습니다. root->next
과 __sync_lock_test_and_set
사이의 루트가 변경되면 어떻게 될까요?
나는이 코드는 다음에 해당한다고 가정 : 내가 말했듯이
T *pop() {
T *temp = root->next;
// are we broken if a push/pop happens here?
return __sync_lock_test_and_set(&root, temp);
}
그래서,이 코드가 올바르지 않은 것을 생각 . 그러나 누군가가 내가 올바른 결론을 내리고 있다고 말할 수 있는가? (잘 작동하는 것을 쓸어내는 것이 싫다.) 내가 의심하는 한 실제로 깨진 경우. 간단한 해결책이 있습니까?
분명히 빈 목록의 팝은 정의되지 않은 동작입니다. 그러나 그것은 실제 질문에 대한 다소 문제입니다. –