2013-04-09 3 views
1

두 개의 스레드를 사용해야합니다. 하나는 행렬에 대해 다양한 연산을 수행하고, 다른 하나는 행렬 연산 프로세스의 다양한 지점에서 가상 메모리를 모니터합니다. 이 메서드는 전역 상태 변수 'flag'를 사용하는 데 필요합니다.C에서 스레드 동기화

지금까지 나는 다음 (간결함을위한 몇 가지 밖으로 떠나)이 있습니다

int flag = 0; 

int allocate_matrices(int dimension) 
{ 
    while (flag == 0) {} //busy wait while main prints memory state 

    int *matrix = (int *) malloc(sizeof(int)*dimension*dimension); 
    int *matrix2 = (int *) malloc(sizeof(int)*dimension*dimension); 

    flag = 0; 
    while (flag == 0) {} //busy wait while main prints memory state 

    // more similar actions... 
} 

int memory_stats() 
{ 
    while (flag == 0) 
    { system("top"); flag = 1; } 
} 

int main() 
{ //threads are created and joined for these two functions } 

당신이 기대하는 것처럼, system("top") 전화가 한 번 발생을의 행렬이 할당 한 다음 프로그램은 무한 루프에 빠진다 . 이것은 분명히 memory_stats 함수에 할당 된 스레드가 이미 작업을 완료했기 때문에 플래그가 다시 업데이트되지 않기 때문입니다.

우아한 방법이 있나요? 메모리 통계를 4 번 인쇄해야한다는 것을 알기 때문에, 각자간에 글로벌 플래그에 대해 바쁜 대기 조건으로 memory_stats 함수에서 4 개의 루프를 작성하는 동안 발생할 수 있습니다. 그러나 그것은 내게 어색한 것처럼 보입니다. 어떤 도움이나 조언을 부탁드립니다.

+0

스레드를 사용하지 않습니까? 이 경우에는 아무런 의미가 없기 때문입니다. 또는 뮤텍스 또는 원자 기본 요소를 사용하십시오. –

+0

이 작업에는 Pthreads를 사용해야합니다. https://computing.llnl.gov/tutorials/pthreads/ –

+0

@ VladLazarenko 네 말이 맞아, 이치에 맞지 않아. 나는이 모든 것들이 순차적으로 쉽게 행해질 수 있으며 내가 선택의 여지가 있다면 그렇게 할 수 있음을 깨닫는다.나에게도 일어난 뮤텍스를 사용했다면, 이론은 전혀 다르겠습니까? 즉, 간헐적 인 바쁜 대기로 4 개의 루프를 작성하는 것보다 더 우아한 해결책이 있습니까? – aquemini

답변

5

하나는 flag 정기적 변수가 있다는 것이다 컴파일러는이 flag = 0;while (flag == 0) {} 간 또는 allocate_matrices() 안쪽이 while에 0이 아닌 값으로 설정 결코 것으로보고있다. 그래서 변수는 0으로 유지되고 루프는 무한하게됩니다. 컴파일러는 스레드에 대해 전혀 몰두합니다.

위의 상황을 방지하기 위해 flagvolatile으로 정의 할 수 있지만 volatile을 추가하면 다른 문제가 발생할 가능성이 높습니다. 한 가지, volatile은 가변 수정의 원 자성을 보장하지 않습니다.

또 다른 문제는 컴파일러가 an infinite loop that has no side effects, it may be considered undefined behavior and anything could happen, or, at least, not what you're thinking should을보고있는 경우 this입니다.

뮤텍스와 같은 적절한 동기화 프리미티브를 사용해야합니다.

3

뮤텍스로 잠글 수 있습니다. 나는 pthread를 사용한다고 가정합니다. 다른 라이센스를 생략 한 컴파일러는 이후에 읽는 모든 https://computing.llnl.gov/tutorials/pthreads/

+1

C11에는 실제로 선택적 [스레드 지원 라이브러리] (http://en.cppreference.com/w/c/thread)가 있습니다. – Zeta

+0

'while' 루프 밖에서'memory_stats()'에 뮤텍스를 사용한다고 가정합니다. 그러면 스레드가 다시 함수를 실행할 수 있습니까? – aquemini

+0

루프를 실행하는 동안 외부로 잠글 수 있지만 왜 그렇게할까요? while 루프가 시작될 때 몇 가지 내용을 읽은 것 같습니다. 플래그를 설정할 때 위험 지역에 도달 했습니까? – cgon

-2

첫째, volatile를 선언하거나 할 필요가 flag 변수 : 여기

pthread_mutex_t mutex; 

pthread_mutex_lock(&mutex); 
flag=1; 
pthread_mutex_unlock (&mutex); 

는 pthreads의, 뮤텍스 및 기타 물건에 대한 아주 좋은 튜토리얼 첫번째.

그런 식으로 시퀀서/event_counter를 사용할 수 있습니다. 하나의 스레드가 변수가 홀수 일 때, 다른 스레드가 짝수 일 때 변수를 증가시킬 수 있습니다. 한 스레드가 항상 변수를 "소유"하고 증분과 함께 소유권을 이전하기 때문에 경쟁 조건이 없습니다. 요령에 대한 가능한 이유의

+0

의'volatile'이라는 스킴을 정확하게 구현하는 데 사용할 수있는'atomic_flag '이 있습니다. 그래서 여러분이 제안한 해결책은 여전히 ​​경쟁 조건을 갖습니다. –

+0

값이 충분히 작 으면 하드웨어가 원자 액세스를 보장합니다 (예 : 32 비트). 두 스레드 중 하나만 모든 상태에서 값을 쓸 수 있으면 경쟁이 없습니다. –

+0

'값이 충분하다면 하드웨어가 원자 접근을 보장합니다. '- 플랫폼에 의존하는 동작처럼 들립니다. 코드를 플랫폼에 독립적으로 사용하려는 경우 좋지 않습니다. –

0

최신 C 표준 인 C11을 따르는 C 컴파일러로 문제를 해결할 수 있습니다. C11에는 쓰레드와 atomic_flag이라는 데이터 유형이 있습니다.이 유형은 기본적으로 스핀 잠금에 사용할 수 있습니다.