2011-03-19 4 views
1

조잡한 스레드 인터럽트를 구현하려고합니다.이 코드 섹션에는 뮤텍스가 필요합니까?

'interruptRequested'변수가 꽤 자주 검사되고 있습니다. 운영 체제 클래스에서 우리는 기아에 대해 배웠습니다 - 여기 또는 비슷한 상황에서 가능합니까? 필자는 예제 프로그램이 실행될 때 예상대로 작동하지만 우연히 될 수 있음을 알고 있습니다.

사실
//Compile with -lpthread 

#include <iostream> 
#include <signal.h> 
#include <sys/types.h> 
#include <time.h> 
#include <unistd.h> 
#include <pthread.h> 

using namespace std; 

bool interruptRequested; 
pthread_mutex_t spamMutex; 
void *Spam(void *); 

int main(int argc, char *argv[]) 
{ 

pthread_t tid; 

interruptRequested = false; 

unsigned long long int timeStarted = time(NULL); 
pthread_create(&tid, NULL, Spam, NULL); 
unsigned long long int difference = 0; 


while (true) 
{ 
    pthread_yield(); 
    difference = (time(NULL) - timeStarted); 
    if (difference >= 5)//Spam the terminal for 5 seconds 
    { 
     //while (pthread_mutex_trylock(&spamMutex)); 
     interruptRequested = true; 
     //pthread_mutex_unlock(&spamMutex); 
     break; 
    } 


} 

return 0; 
} 

void *Spam (void *arg) 
{ 
while (true) 
{ 
    //while (pthread_mutex_trylock(&spamMutex)); 
    if (interruptRequested == true) 
    { 
     //pthread_mutex_unlock(&spamMutex); 
     break; 
    } 
    //pthread_mutex_unlock(&spamMutex); 
    cout << "I'm an ugly elf" << endl; 
    pthread_yield(); 
} 

interruptRequested = false; 
pthread_exit (0); 
} 

, 실제 코드에서 나는 시차 방식을 사용하고 있지 않다 : 여기

내가 뭘하는지의 단순화 된 버전입니다. 내 프로그램은 서버에서 메시지를 수신하고 그 시점에서 스레드를 인터럽트해야합니다.

답변

0

예. 먼저 상호 배타를 사용하여 각각의 블록에서 읽기 및 쓰기를 interruptRequested으로 보호해야합니다.

이 예상대로 작동하려면이 표시 되더라도 실제로 그렇지 않을 수 있습니다. 99 %의 성공률은 소프트웨어에서 허용되지 않습니다. 또한 테스트 프로그램은 사소한 것입니다. 현실 세계에서 (조용히 또는 신비하게) 실패 할 가능성이 있습니다.

로크 대신 대체 휘발성 (또는 많은 경우 원자)을 사용하면 입니다. 비록 가벼운 하중에서도 정확하게 이 나타나기는하지만,이 모델은 결국 실패 할 것입니다. 약간의 코너 케이스가 있지만, 당신은 휘발성의 협회를 잠금을 사용하여 적절한 디자인을 대신하여 포기해야합니다. 실제로 interruptRequestedint으로 만들고 증가/감소 만 사용하여이를 테스트 할 수 있습니다. 과부하가 걸리는 경우 [0 ... 1]을 빨리 초과 할 수 있습니다.

interruptRequested를 선언/읽기/쓰기 할 때 종종 휘발성 및/또는 원자를 사용합니다 (다시 말하면, 배우는 동안 int/inc/dec/경계 검사를 권장합니다). 읽기와 쓰기가 모두 잠겨 있다면 (이 경우에 있어야 함), 원자 읽기/쓰기를 사용하면 도움이되지 않습니다.

프로그램과 관련하여 조건 (pthread_cond_t)을 선택하는 것이 좋습니다.

1

작성된 것처럼이 코드는 컴파일러가 작업 내에서 interruptRequested에 대한 검사를 최적화하지 않을 수 있기 때문에 반드시 작동하는 것은 아닙니다. 이것은 생성 된 코드가 단지 while (true) 루프를 가질 수 있다는 것을 의미합니다.

이 문제를 방지하려면 컴파일러에서 변수가 다른 곳에서 수정 될 수 있음을 인식해야합니다. interruptRequestedvolatile으로 표시하면 컴파일러에 최적화되지 않아야 함을 나타냅니다. 대부분의 컴파일러는 뮤텍스의 사용이 뮤텍스 내부에서 참조 된 변수가 외부 적으로 수정 될 수 있음을 나타낼만큼 충분히 똑똑하기 때문에 뮤텍스를 사용하는 것도 좋은 생각입니다.

+0

+1 예, 휘발성 속성을 사용하는 것이 좋습니다. – fabrizioM

0

일반적으로 공유 데이터는 뮤텍스로 처리해야한다고 생각합니다.

이 특정 경우에는 하나의 스레드 만 제어 변수를 업데이트하므로 뮤텍스를 사용하는 것이 너무 많을 수 있습니다. 몇 밀리 초의 액티브 루프에서 잠을 자면 메인 루프를 수시로 활성화 할 수 있습니다.

관련 문제