programing

pthread_cond_wait(&cond_t, &mutex);는 뮤텍스를 잠금 해제하고 잠글 수 있습니까?

nicescript 2022. 8. 9. 22:10
반응형

pthread_cond_wait(&cond_t, &mutex);는 뮤텍스를 잠금 해제하고 잠글 수 있습니까?

사용하고 있다pthread_cond_wait(&cond_t, &mutex);이 함수가 왜 두 번째 파라미터로 뮤텍스 변수가 필요한지 궁금합니다.

pthread_cond_wait()pthread_cond_wait() ( 잠가 버립니다.pthread_cond_wait()

조건 변수와 그 사용법에 관한 많은 텍스트가 있기 때문에 추한 세부 사항은 지루하게 하지 않겠습니다.이것이 존재하는 이유는 술어 상태의 변경을 통지할 수 있도록 하기 위해서입니다.조건 변수와 그 뮤텍스 관련성을 올바르게 사용하려면 다음 사항이 중요합니다.

  • pthread_cond_wait()는 동시에 뮤텍스잠금을 해제하고 조건 변수의 시그널링을 기다립니다.따라서 mutex를 호출하기 전에 항상 소유권이 있어야 합니다.

  • pthread_cond_wait()mutex를 잠근 상태로 되돌립니다.따라서 mutex가 잠긴 후 다른 곳에서 사용할 수 있도록 하려면 mutex를 잠금 해제해야 합니다.조건 변수가 시그널링되었기 때문에 반환이 발생했는지 여부는 관련이 없습니다.스플리어스 웨이크업 가능성에 관계없이 술어를 확인해야 합니다.

  • 뮤텍스의 목적은 조건 변수를 보호하는 것이 아니라 조건 변수가 시그널링 메커니즘으로 사용되는 술어를 보호하는 것입니다.이것은 pthread 조건 변수와 그 뮤텍스의 가장 자주 오해되는 관용어입니다.조건 변수에는 상호 제외 보호가 필요하지 않습니다. 술어 데이터에는 보호가 필요합니다.술어는 조건 변수/뮤텍스 쌍의 사용자에 의해 감시되고 있는 Outside-state로 간주합니다.

예를 들어, 부울 플래그를 기다리는 것은 사소하지만 명백히 잘못된 코드 조각입니다.fSet:

bool fSet = false;

int WaitForTrue()
{
    while (!fSet)
    {
        sleep(n);
    }
}

큰 입니다.fSet는 전혀 보호되지 않습니다.여기서는 많은 일이 잘못될 수 있습니다.예: while-conditon을 평가할 때부터 대기(또는 회전)를 시작할 때까지 값이 변경될 수 있습니다.변경 알림을 놓치면 불필요하게 대기하게 됩니다.

적어도 술어는 어떻게든 보호되도록 이것을 조금 바꿀 수 있습니다.술어의 수정과 평가 양쪽에서 상호 배제는 뮤텍스를 쉽게 제공할 수 있다.

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;

int WaitForTrue()
{
    pthread_mutex_lock(&mtx);
    while (!fSet)
        sleep(n);
    pthread_mutex_unlock(&mtx);
}

음, 그건 충분히 간단해 보이는데..이제 술어를 평가하려면 먼저 (mutex를 래치하여) 독점적으로 접근해야 합니다.하지만 이것은 여전히 큰 문제이다.뮤텍스를 잠갔지만 루프가 끝날 때까지 절대 풀지 않습니다.다른 모든 사용자가 규칙에 따라 뮤텍스 잠금을 기다린 후 평가 또는 수정하는 경우fSet우리가 뮤텍스를 포기할 때까지 절대 그럴 수 없어이 경우에 그렇게 할 수 있는 유일한 "누군가"는 우리입니다.

여기에 층을 더 추가하는 것은 어떨까요?이게 먹힐까?

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;

int WaitForTrue()
{
    pthread_mutex_lock(&mtx);
    while (!fSet)
    {
        pthread_mutex_unlock(&mtx);
        // XXXXX
        sleep(n);
        // YYYYY
        pthread_mutex_lock(&mtx);
    }
    pthread_mutex_unlock(&mtx);
}

'잘 될 거예요하겠지만 많이 는 않아요.「 」의 XXXXX ★★★★★★★★★★★★★★★★★」YYYYY 때문에 는 있지 .fSet(단,든지 ( 다른 수 있고 b) 가능하다.fSet (하면 (c) 뮤텍스, (c) 뮤텍스, (c) 마쳐야 알수sleep()다시 한 번 뮤텍스 잠금을 취득하고 다른 체크를 위해 루프를 돌립니다.

더 나은 방법이 있을 거야어떻게든 뮤텍스를 풀어주고 술어의 변화가 일어났을지도 모른다는 신호를 기다리는 방법이 있을 거야마찬가지로 중요한 것은 신호를 수신하고 코드로 돌아왔을 때 이미 잠금장치를 소유하고 있어야 한다는 것입니다.이 잠금장치는 술어 데이터를 확인할 수 있는 권한을 부여합니다.이것이 바로 조건 변수가 제공하도록 설계된 것입니다.


동작 중인 조건 변수

condition-variable + mutex 쌍을 입력합니다.mutex는 술어 변경 또는 체크에 대한 접근을 보호하는 한편, 조건 변수는 술어 상호 제외를 사용하여 변경을 감시하는 시스템을 셋업하고, 더 중요한 것은 변경을 (어쨌든) 원자적으로 감시하는 것입니다.

int WaitForPredicate()
{
    // lock mutex (means:lock access to the predicate)
    pthread_mutex_lock(&mtx);

    // we can safely check this, since no one else should be 
    // changing it unless they have the mutex, which they don't
    // because we just locked it.
    while (!predicate)
    {
        // predicate not met, so begin waiting for notification
        // it has been changed *and* release access to change it
        // to anyone wanting to by unlatching the mutex, doing
        // both (start waiting and unlatching) atomically
        pthread_cond_wait(&cv,&mtx);

        // upon arriving here, the above returns with the mutex
        // latched (we own it). The predicate *may* be true, and
        // we'll be looping around to see if it is, but we can
        // safely do so because we own the mutex coming out of
        // the cv-wait call. 
    }

    // we still own the mutex here. further, we have assessed the 
    //  predicate is true (thus how we broke the loop).

    // take whatever action needed. 

    // You *must* release the mutex before we leave. Remember, we
    //  still own it even after the code above.
    pthread_mutex_unlock(&mtx);
}

위의 루프를 시그널링하는 다른 스레드에는 몇 가지 방법이 있습니다.다음 두 가지가 가장 일반적인 방법입니다.

pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cv);

다른 방법으로는...

pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mtx);

각각은 다른 내적 행동을 가지고 있고 나는 당신이 그 차이에 대해 숙제를 하고 어떤 것이 특정한 상황에 더 적합한지 결정하기를 초대합니다.전자는 잠재적으로 보증되지 않은 웨이크업을 도입하는 대신 더 나은 프로그램 흐름을 제공합니다.후자는 이러한 경각심을 줄이지만 컨텍스트 시너지 효과는 낮습니다. 중 하나가 샘플에서 작동하며, 각 것이 대기 루프에 어떤 영향을 미치는지 실험할 수 있습니다.단, 가장 중요한 것은 다음 두 가지 방법으로 이 명령을 이행하는 것입니다.

뮤텍스가 잠기지 않는 한 술어 조건을 변경하거나 체크하지 마십시오. 번도.


심플 모니터 스레드

이러한 조작은 특정 술어 조건에 따라 동작하는 모니터스레드에서 흔히 볼 수 있습니다(SAN의 에러 체크)는 일반적으로 다음과 같습니다.

void* monitor_proc(void *pv)
{
    // acquire mutex ownership
    //  (which means we own change-control to the predicate)
    pthread_mutex_lock(&mtx);

    // heading into monitor loop, we own the predicate mutex
    while (true)
    {
        // safe to check; we own the mutex
        while (!predicate)
            pthread_cond_wait(&cv, &mtx);

        // TODO: the cv has been signalled. our predicate data should include
        //  data to signal a break-state to exit this loop and finish the proc,
        //  as well as data that we may check for other processing.
    }

    // we still own the mutex. remember to release it on exit
    pthread_mutex_unlock(&mtx);
    return pv;
}

보다 복잡한 모니터 스레드

알림 시스템을 고려하여 이 기본 양식을 수정하면 알림을 받은 후 mutex를 잠근 상태로 유지할 필요가 없습니다.단, 이 변경은 그다지 중요하지 않습니다.다음 모니터 프로시저는 서비스가 제공되고 있음을 확인하면 일반 처리 중에 뮤텍스를 래치 상태로 유지하지 않습니다.

void* monitor_proc(void *pv)
{
    // acquire mutex ownership
    //  (which means we own change-control to the predicate)
    pthread_mutex_lock(&mtx);

    // heading into monitor loop, we own the predicate mutex
    while (true)
    {
        // check predicate
        while (!predicate)
            pthread_cond_wait(&cv, &mtx);

        // some state that is part of the predicate to 
        // inform us we're finished
        if (break-state)
            break;

        // TODO: perform latch-required work here.

        // unlatch the mutex to do our predicate-independant work.
        pthread_mutex_unlock(&mtx);

        // TODO: perform no-latch-required work here.

        // re-latch mutex prior to heading into wait
        pthread_mutex_lock(&mtx);            
    }

    // we still own the mutex. remember to release it on exit
    pthread_mutex_unlock(&mtx);
    return pv;
}

누가 그런 을 어디에 사용하겠는가? 음, 당신의 "예약"이 작업 큐의 "상태"일 뿐만 아니라 루프를 멈추고 종료하라는 몇 가지 플래그라고 가정해 보자.뭔가 다르다는 통지를 받으면 루프를 계속 실행해야 하는지 여부를 확인하고 큐에서 일부 데이터를 삭제해야 하는지 결정합니다.큐를 변경하려면 뮤텍스를 래치해야 합니다(그 "상태"는 술어의 일부입니다).데이터를 팝하면 로컬에 데이터를 저장하여 큐스테이트에 관계없이 처리할 수 있기 때문에 뮤텍스를 해방하고 작업을 수행한 후 다음 처리를 위해 뮤텍스를 요구합니다.상기의 개념을 코드화하는 방법에는, 적절한 사용을 포함한 많은 방법이 있습니다.pthread_cond_broadcast등입니다만, 기본적인 형식은 이해할 수 있으면 좋겠습니다.

이것은 기대했던 것보다 꽤 긴 시간이었지만, 이것은 pthread-programming을 배우는 사람들에게 큰 장애물이 되어, 여분의 시간과 노력을 들일 가치가 있다고 생각합니다.뭔가 도움이 됐길 바라.

첫 번째 스레드가 호출하면 뮤텍스가 해제되고 상태가 될 때까지 대기합니다.cond_tcomplete로 표시되며 mutex사용할 수 있습니다.

따라서 다른 스레드에서 호출될 때 대기하는 스레드는 아직 "웨이크업"되지 않습니다. mutex먼저 잠금을 해제해야 합니다.그 후에야 첫 번째 스레드가 잠길 가능성이 있습니다.즉, "mutex가 정상적으로 돌아왔을잠겼으며 발신측 스레드에 의해 소유됩니다."

네, 잠금이 해제되고 조건이 충족될 때까지 기다린 후 전달된 뮤텍스를 재쿼킹할 수 있을 때까지 기다립니다.

언급URL : https://stackoverflow.com/questions/14924469/does-pthread-cond-waitcond-t-mutex-unlock-and-then-lock-the-mutex

반응형