2015-01-17 2 views
2

링크 (http://www.cplusplus.com/reference/mutex/mutex/try_lock/)에서 샘플은 1부터 100000까지만 값을 반환 할 수 있다고 선언했습니다. 0을 출력 할 수 없다고 선언합니까?뮤텍스 try_lock에 대한 cpp 사양의 오류?

어떤 경우
// mutex::try_lock example 
#include <iostream>  // std::cout 
#include <thread>   // std::thread 
#include <mutex>   // std::mutex 

volatile int counter (0); // non-atomic counter 
std::mutex mtx;   // locks access to counter 

void attempt_10k_increases() { 
    for (int i=0; i<10000; ++i) { 
    if (mtx.try_lock()) { // only increase if currently not locked: 
     ++counter; 
     mtx.unlock(); 
    } 
    } 
} 

int main() 
{ 
    std::thread threads[10]; 
    // spawn 10 threads: 
    for (int i=0; i<10; ++i) 
    threads[i] = std::thread(attempt_10k_increases); 

    for (auto& th : threads) th.join(); 
    std::cout << counter << " successful increases of the counter.\n"; 

    return 0; 
} 

, 그것은 try_lock "이 때 다른를 외관상 실패 할 수 있습니다 정말 일을 얻을 0

을 결코하는 방법에 대한 분명하지 '어떻게 2를 얻기 위해?'대답 쉽지만, thread는 뮤텍스에 락을 가지고 있지만, 이러한 상황에서 반복 호출은 어떤 시점에서 성공할 것이다. 그러나 참이면 샘플은 0을 반환 할 수 있으며 어떤 경우에는 1을 반환 할 수도있다.

그러나이 사양 샘플이 true로 선언되고 0을 출력 할 수 없으면 "fail spuriously"에 대한 단어가 사실이 아닐 수 있습니다.

+0

much closer 인 cppreference.com을 사용하는 것이 더 안전합니다. 10000 회에 '반복 호출'을 부르겠습니까? – marc

+1

아 [cplusplus.com의 기쁨 (http://stackoverflow.com/q/6520052/596781). 비록 당신이 현학적이라면, 사이트는 0이 불가능하다고 주장하지 않습니다. 그것은 단지 1-100000이 가능하다고 주장합니다. –

+0

나는 그것이 언어 내에서 공식화하기가 매우 어려운 글로벌 진행 보장의 가장자리 사례 중 하나라고 말하고 싶지만,하지만 일종의 합리적인 플랫폼에서 그 가정 어디에, try_lock' '의 실패는 * 일부 * 다른 스레드를 의미한다 * 어느 시점에서 * 진전이있었습니다. –

답변

2

입니다 :

30.4.1.2/14 [thread.mutex.requirements.mutex]

구현 다른 thread에 의해 보관 유지되어 있지 않아도, 락을 취득 할 수없는 경우가 있습니다. [주의 :이 스퓨리어스의 실패는 일반적으로 이지만, 간단한 비교와 교환을 기반으로하는 흥미로운 구현이 가능하다. (29 절). -end note]

따라서 try_lock이 모두 실패하면 0을받을 수 있습니다.

또한, cplusplus.com를 사용하지 마십시오, 그것은 실수를 많이 가진의 long history 있습니다.
표준

0

try_lock은 다른 스레드가 잠금을 보유하고 방금 해제 한 경우 실패 할 수 있습니다. 당신은 "이 상황에서 반복되는 전화는 어느 시점에서 성공할 것"이라고 읽었습니다. try_lock에 대한 10,000 건의 호출을 수행하면 "반복 호출"로 간주되며 그 중 하나가 성공합니다.

+0

이 당신도 0을 얻을 수 있다는 것을 의미하지만, 우리가 cplusplus.com에 말을 존중 경우뿐만 불가능 선언 (전용 값 [1..100000] 선언) : – aefimov

-1

당신은 공을 얻을 수 없다 :

try_lock()에 대한 첫 번째 호출이 발생

뮤텍스 잠금이 해제됩니다 (여기 처음 인 스레드 중요하지 않습니다). 즉, 10 개의 스레드 중 1 개가 뮤텍스를 잠그기 때문에 try_lock()이 성공합니다.

당신은 하나 얻을 수 있습니다 : 이제

void attempt_10k_increases() { for (int i=0; i<10000; ++i) { if (mtx.try_lock()) { // thread 1 to 9 are here ++counter; // thread 0 is here mtx.unlock(); } } }

  • 우리가 OS 스케줄러가 실행되지하기로 결정했습니다 말 :

    • 스레드 0이 뮤텍스를 잠금 관리 말할 수 있습니다 스레드 0 잠시 동안. 그 동안 스레드 1 ~ 9는 계속 실행 중이며 try_lock()을 호출하고 실패합니다. 스레드 0은 뮤텍스를 보유하고 있기 때문입니다.

      • 스레드 1 - 9가 완료되었습니다. 그들은 한번도 뮤텍스를 얻지 못했습니다.
      • 스레드 0이 다시 풀립니다. 뮤텍스의 잠금을 해제하고 마침.
      • 카운터 표준은 다음 말한다 지금 1.
+0

당신이 모든 스레드를 필요로이를 얻으려면 10000 번 실패에 대한 try_lock, 한 스레드가 9999 번 실패하고 마지막 호출 성공. – aefimov

+0

@aefimov 첫 번째 호출이 성공할 가능성이 큽니다. "이 함수는 다른 스레드가 뮤텍스에 대한 잠금을 가지고 있지 않을 때 가짜로 실패 할 수 있습니다. 그러나 이러한 상황에서 반복 호출은 어느 시점에서 성공합니다." 난 내 예는 조금 바보 같아,하지만 난이 "어떤 점에서"thread0'잠금 해제 후 인으로 간주()'내 예에 처음. 그래도 그렇게할만한 것은 아닙니다. 그리고 나는 모든 스레드가 동시에 10k 통화에 실패 할 가능성이 있다고 생각하지 않습니다. – Xaqq