뮤텍스를 잠그지 않고 pthread_cond_signal 호출


85

pthread_cond_signal 을 호출하기 전에 뮤텍스 를 잠그고 호출 한 후 뮤텍스를 잠금 해제 해야한다고 어딘가에서 읽었 습니다.

pthread_cond_signal () 루틴은 조건 변수에서 대기중인 다른 스레드를 신호 (또는 깨우기)하는 데 사용됩니다. 뮤텍스가 잠긴 후에 호출해야하며 pthread_cond_wait () 루틴이 완료 되려면 뮤텍스를 잠금 해제해야합니다.

내 질문은 : 뮤텍스를 잠그지 않고 pthread_cond_signal 또는 pthread_cond_broadcast 메서드 를 호출해도 괜찮지 않습니까?

답변:


143

조건과 신호를 변경하는 코드 경로에서 뮤텍스를 잠그지 않으면 wakeup이 손실 될 수 있습니다. 다음 프로세스 쌍을 고려하십시오.

프로세스 A :

pthread_mutex_lock(&mutex);
while (condition == FALSE)
    pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

프로세스 B (잘못된) :

condition = TRUE;
pthread_cond_signal(&cond);

그런 다음 다음 condition과 같이 시작하는 명령어 인터리빙 가능성을 고려하십시오 FALSE.

Process A                             Process B

pthread_mutex_lock(&mutex);
while (condition == FALSE)

                                      condition = TRUE;
                                      pthread_cond_signal(&cond);

pthread_cond_wait(&cond, &mutex);

condition지금 TRUE하지만, 프로세스 A는 조건 변수에 붙어 대기 - 그것은 웨이크 업 신호를 놓쳤다. 프로세스 B를 변경하여 뮤텍스를 잠그면 :

프로세스 B (정확함) :

pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

... 위의 상황이 발생할 수 없습니다. 웨이크 업을 놓치지 않습니다.

( 실제로 자체를. 뒤에 이동할 있지만 이로 인해 스레드의 최적 스케줄링이 떨어질 수 있으며 조건 자체를 변경하기 때문에이 코드 경로에 이미 뮤텍스를 잠근 것입니다).pthread_cond_signal()pthread_mutex_unlock()


4
@Nemo : 예, "올바른"경로 에서 뮤텍스 잠금 해제 후에 이동할 pthread_signal_cond() 있습니다. 을 호출하는 지점에서 pthread_signal_cond()조건 자체를 수정하기 위해 이미 뮤텍스를 잠 가야 한다고 말하는 것이 더 정확할 것입니다.
caf

@Nemo : 예, 코드가 깨져서 "잘못된"것으로 표시되는 이유입니다.이 질문을하는 사람들은 종종 신호 경로에 완전히 잠금 해제하는 것을 고려하는 것이 제 경험입니다. 아마도 당신의 경험이 다를 것입니다.
caf

10
그만한 가치가 있기 때문에 신호 전 또는 후에 잠금을 해제할지 여부에 대한 질문은 실제로 대답하는 것이 사소한 일이 아닙니다. 이후 잠금 해제는 우선 순위가 낮은 스레드가 우선 순위가 높은 스레드에서 이벤트를 훔칠 수 없도록 보장하지만 우선 순위를 사용하지 않는 경우 신호 전에 잠금을 해제하면 실제로 시스템 호출 / 컨텍스트 전환 수를 줄이고 전반적인 성능을 향상시킵니다.
R .. GitHub의 STOP 돕기 ICE

1
@R .. 당신은 그것을 거꾸로 가지고 있습니다. 신호 전에 잠금을 해제하면 시스템 호출 수가 증가하고 전체 성능이 저하됩니다. 잠금 해제 전에 신호를 보내는 경우 구현은 신호가 스레드를 깨울 수 없다는 것을 알고 (cv에서 차단 된 스레드는 앞으로 진행하기 위해 뮤텍스가 필요하기 때문에) 빠른 경로를 사용할 수 있습니다. 잠금 해제 후 신호를 보내면 잠금 해제와 신호 모두 스레드를 깨울 수 있으므로 둘 다 비용이 많이 드는 작업입니다.
David Schwartz

1
@Alceste_ : POSIX의 다음 텍스트를 참조하십시오 . "스레드가 pthread_cond_timedwait()또는 pthread_cond_wait()작업에 특정 뮤텍스를 지정한 상태에서 조건 변수를 기다릴 때 해당 뮤텍스와 조건 변수 사이에 동적 바인딩이 형성되어 조건 변수에서 하나의 스레드가 차단되었습니다.이 시간 동안 스레드가 다른 뮤텍스를 사용하여 해당 조건 변수를 대기하려는 시도의 효과는 정의되지 않았습니다. "
caf

51

이 설명서에 따르면 :

pthread_cond_broadcast()또는 pthread_cond_signal()기능 은 현재 뮤텍스 소유 여부를 스레드에 의해 호출 할 수 있습니다 스레드가 호출하는 것을 pthread_cond_wait()pthread_cond_timedwait()자신을 기다리는 동안 조건 변수와 관련된 한을; 예측 가능한 일정 행동이 필요한 경우, 그 뮤텍스는 스레드의 호출에 의해 고정된다 pthread_cond_broadcast()거나 pthread_cond_signal().

예측 가능한 스케줄링 동작 명령문 의 의미는 Comp.programming.threads에서 Dave Butenhof ( POSIX 스레드를 사용한 프로그래밍의 저자)에 의해 설명되었으며 여기에서 사용할 수 있습니다 .


6
Dave Butenhof의 메일 연결에 +1. 나는 항상이 문제에 대해 스스로 궁금해했지만, 이제는 ... 오늘 중요한 것을 배웠습니다. 감사.
Nils Pipenbrinck

예측 가능한 스케줄링 동작이 필요한 경우 원하는 순서대로 한 스레드에 명령문을 넣거나 스레드 우선 순위를 사용하십시오.
Kaz

7

샘플 코드에서 프로세스 B는 condition먼저 뮤텍스를 잠그지 않고 수정합니다 . 프로세스 B가 수정하는 동안 단순히 뮤텍스를 잠근 다음을 호출하기 전에 뮤텍스를 잠금 해제하면 pthread_cond_signal문제가 없을 것입니다 .--- 내가 맞습니까?

저는 직관적으로 caf의 위치 가 옳다고 믿습니다 pthread_cond_signal. 뮤텍스 잠금을 소유하지 않고 호출 하는 것은 나쁜 생각입니다. 그러나 caf의 는 실제로이 입장을 뒷받침하는 증거가 아닙니다. 뮤텍스를 먼저 잠그지 않는 한 뮤텍스에 의해 보호되는 공유 상태를 수정하는 것이 나쁜 생각이라는 훨씬 약한 (실제로 자명 한) 입장을 뒷받침하는 단순한 증거 일뿐입니다.

누구든지 호출 pthread_cond_signalpthread_mutex_unlock올바른 동작 을 생성하지만 호출 pthread_mutex_unlockpthread_cond_signal잘못된 동작 을 생성 하는 샘플 코드를 제공 할 수 있습니까 ?


3
사실, 난 내 질문의 중복 생각 이 하나의 대답은 그것의 벌금, 당신은 할 수 있습니다 "입니다 완전히 뮤텍스 잠금을 소유하지 않고가 pthread_cond_signal 호출합니다. 더 정확성 문제가 없습니다.하지만 일반적인 구현에 당신은 영리한 최적화를 놓치지거야 pthreads 내부 깊숙이 있으므로 잠금을 유지하면서 pthread_cond_signal을 호출하는 것이 약간 바람직합니다. "
Quuxplusone 2012-06-15

나는 내 대답의 마지막 단락에서 이것을 관찰했습니다.
caf

여기에 좋은 시나리오가 있습니다. stackoverflow.com/a/6419626/1284631 동작이 올바르지 않다고 주장하는 것이 아니라 동작이 예상과 다를 수있는 경우 만 나타냅니다.
user1284631

pthread_cond_signal후 호출 pthread_mutex_unlock이 신호가 "잘못된"스레드 (술어의 변경 사항을 확인한 후 차단 된 스레드)를 포착하기 때문에 웨이크 업이 손실 될 수 있는 샘플 코드를 생성 할 수 있습니다. 이는 동일한 조건 변수가 둘 이상의 술어에 사용될 수 있고 pthread_cond_broadcast어쨌든 드물고 깨지기 쉬운 패턴 인를 사용하지 않는 경우에만 문제가됩니다 .
David Schwartz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.