2013-08-23 2 views
3

나는 (데이비드 Butenhof에 의해) POSIX 스레드 프로그래밍을 읽고있다, 그는 pthread와 라이브러리를 사용하여 언급 :pthread 라이브러리를 통한 메모리 가시성?

가 뮤텍스를 잠금을 해제 할 때 볼 수있는 스레드 값간에 메모리

직접 또는에서 대기로를 조건 변수는 나중에 동일한 뮤텍스를 잠그는 임의의 스레드에서 보이는 일 수 있습니다. 다시, 뮤텍스가 잠금 해제되기 전에 쓰여진 데이터 은 잠금 전에 쓰기가 발생하더라도 뮤텍스를 잠그는 스레드 인 에서 반드시 볼 필요는 없습니다.

모든 갑자기, 나는 다음과 같은 코드가 유효한지 여부를 궁금해 :

스레드 A :

strcpy(buffer, "hello world"); 
pthread_spin_lock(&lock); // assuming the mutex in the statement above can be interchanged with spinlock. I don't see why it can't 
pthread_spin_unlock(&lock); 

스레드 B :

pthread_spin_lock(&lock); 
pthread_spin_unlock(&lock); 
// read buffer; assuming thread B has a copy of the pointer somehow 

내 질문은 : 스레드 수 B 버퍼에서 "hello world"를 참조 하시겠습니까? 그의 성명서에 따르면, 그것은해야한다. 나는 "일반적인"방법은 자물쇠로 공유 "자원"을 보호하는 것입니다 이해합니다. 하지만 strcpy()가 임의의 시간에 발생한다고 가정 해 봅시다. 프로그램의 수명이 다 된 시점에서 한 번만 발생할 수 있습니다. 스레드 A가 pthread_spin_unlock()을 호출 한 후에 스레드 B가 어떻게 든 pthread_spin_lock()을 호출한다고 가정 해 봅시다 :

: 다른 스레드에서 버퍼를 볼 수 있도록 변경하는 빠른 방법이 있습니까? 이식성이 문제가 아니며 CentOS를 사용한다고 가정 해 보겠습니다. 내가 생각할 수있는 한 가지 대안은 mmap()을 사용하지만 pthread 라이브러리를 사용하지 않고 모든 변경 사항을 전역으로 볼 수 있는지 여부를 확신하지 못하는 것입니다.

+1

mmap() 개념은 여러 프로세스가 동일한 메모리를 볼 수 있도록 허용한다고 생각합니다. 스레드는 말할 것도 없습니다. – Jiminion

+0

@Jim 귀하의 회신에 감사드립니다. 음 ... mmap()은 아마도 MAP_SHARED와 함께 작동합니다. 더 빠른 방법이 있는지 확실하지 않습니다. – Hei

답변

1

저는 이것을 올바르게 이해했다고 생각하지 않습니다 : 잠금 장치는 마술처럼 데이터를 전송하지 않으며, 안전하게 데이터를 이동할 수있는 스레드 간의 통신 형태입니다.

질문에 많은 가정을합니다. 사실, 가정이 모두 유지되는 한 이 존재하지 않으면 자물쇠가 동등하게 적용됩니다. 동시 프로그래밍의 문제점은 일반적으로 과 같은 가정을 할 수 없다는 것입니다..

스레드 A가 메모리에 변경이있는 경우는 그 (캐싱 컴파일러 최적화 변덕 허용) 즉시 B 스레드하는 표시된다. 이것은 잠금 장치의 유무와 상관없이 항상 사실입니다. 그러나 잠금 장치가 없으면 쓰기가 아직 완료되었거나 시작되었다는 보장이 없습니다.

먼저 잠금 세트가있는 공유 데이터에만 쓰는 것으로 가정합니다 (필수). 마지막 부분은 먼저 잠금없이 작성하려고하면 어떤 나쁜 일이 일어날 수 있는지 알려줍니다.

"잠금 전에 쓰기가 발생하더라도"무슨 뜻인지는 잘 모르겠지만, 정확하게는 동시 프로그램을 괴롭히는 다양한 경쟁 조건 및 메모리 캐싱 효과를 나타냅니다. 잠금은 실제로 데이터를 전송하지 않을 수 있지만 컴파일러가 호출을 통해 메모리를 동기화하도록 강제로 코딩됩니다 ("메모리 장벽").

+0

나는 어떤 가정도 할 수 없다는 것을 이해하지만 pthread (또는 다른 스레드 라이브러리)가 코드를 작성할 수 있도록 보장 할 수는 있습니다. 내 게시물은 보증을 더 잘 이해할 수 있도록 도와 주려고 노력했습니다. – Hei

+0

그리고 스레드 A가 수행 한 쓰기가 스레드 B의 읽기 전에 완료되었다는 것을 보장 할 수있는 이유는 스레드 A가 스레드 B가 그렇게하도록 신호를 보낼 때까지 스레드 B가 읽으려고 시도하지 않는다는 것입니다. 그러나, 내가 "신호"라고 말할 때, 나는 pthread_cond_signal이나 메모리 장벽과 관련된 어떤 종류의 신호도 의미하지 않습니다. 신호는 파이프, TCP 소켓 등을 통해 수행 할 수 있습니다 (예, 바보 같은 소리로 들리지만 내 자신의 이유가 있습니다). – Hei

+0

예, 신호를 보내는 많은 방법이 있지만 메모리 일관성을 보장하기 위해 일종의 메모리 장벽이 필요합니다. 운 좋게도 외부 함수를 호출하면 보통 그렇게 할 수 있습니다. 따라서 자연스럽게 발생합니다. 장벽이 없으면 컴파일러는 레지스터에 메모리에 쓴 것으로 생각한 데이터를 자유롭게 보관하거나 관련이 없다고 생각되는 식을 재정렬 할 수 있습니다. 사실 컴파일러는 외부에서 알 수없는 한 전체 프로그램을 완전히 다시 작성할 수 있습니다. 불행히도 몇 가지 예방 조치를 취하지 않으면 스레드가 깨질 수 있습니다. – ams

관련 문제