2010-07-30 6 views
2

: 우리는 두 개의 스레드를 생성휘발성 및 멀티 스레딩? 다음 코드에서

#include <pthread.h> 
#include <unistd.h> 
#include <stdio.h> 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
int ready = 0; 

wait() 
{ 
    int i; 
    do 
    { 
     usleep(1000); 
     pthead_mutex_lock(&mutex); 
     i = ready; 
     pthread_mutex_unlock(&mutex); 
    } while (i == 0); 
    printf("Finished\n"); 
} 

signal() 
{ 
    pthead_mutex_lock(&mutex); 
    ready = 1; 
    pthread_mutex_unlock(&mutex); 
} 

우리는 우리는 또한 적극적으로 최적화 컴파일러를 얻을 하나 개의 스레드에서 대기를 호출 한 다음 다른에서 신호를 호출합니다.

이제 코드가 예상대로 동작할까요? 아니면 정상적으로 작동하려면 준비가 필요합니까? 다른 컴파일러와 라이브러리가 다르게 처리합니까?

편집 : 나는 그 주위에 최적화를 방지하거나 컴파일러가 일반적으로 라운드 함수 호출을 최적화하지 못하는 뮤텍스 함수가있을 수 있기를 바랍니다.

참고 : 아직 코드를 컴파일하고 테스트하지 않았으므로 기회가있을 때 수행 할 것입니다.

답변

-1

예, 여기에 항상 volatile int ready = 0;이 필요합니다. 완전히 휴대용 인 - - 당신은 몇 가지 코드 주위에 최적화 하시겠어요 경우

업데이트
, 당신은 (당신의 컴파일러를 지원하는 경우) 또는 코드 주위에 #pragma 지시어를 사용할 수 있습니다 파일을 분리하는 코드를 이동 이러한 파일을 거의 또는 거의 최적화하지 않고 컴파일하십시오.
ready 변수는 최적화하려는 다른 모듈에서 사용할 수 있으므로 volatile 키워드를 사용해야 할 수도 있습니다.

+0

제 편집을 참조하십시오. – doron

+0

휴대용이 아닙니다. pragma는 컴파일러 최적화를 방해 할 수 있지만, 컴파일러가 수행 할 수있는 최적화는 원칙적으로 칩셋, CPU, 메모리 컨트롤러 등에 의해 수행 될 수 있습니다. –

2

컴파일러가 라이브러리 함수 호출이있는 전역 변수에 대해 아무 것도 가정하지 않으면 놀랍습니다. 즉 휘발성은 아무런 댓가를 치르지 않을 것이고, 그것은 당신의 의도를 보여줍니다. 나는 그것을 거기 넣었다.

+1

따라서 최적화 프로그램이 해당 라이브러리 함수의 코드를 조사하지 않는다고 가정하고 있습니까? 오늘은 아마도 사실 일지 모르지만 내년이 아닐 수도 있습니다. – Darron

+0

@Darron : 컴파일러는 DLL에서로드하는 코드를 볼 수 없습니다. – Puppy

+0

일부 라이브러리는 DLL입니다. 모든 옵티 마이저가 컴파일 타임에 실행되는 것은 아닙니다. 기계 코드에 대한 Just In Time 옵티 마이저에 대한 실험이있었습니다. – Darron

-1

여기서는 최적화가 필요할 때 휘발성이 필요합니다. 그렇지 않으면 ready의 읽기를 while 루프 밖으로 합법적으로 이동할 수 있습니다.

표준에 의해 약속되지 않은 최적화에 대한 제한 사항은 현재로서는 좋지만 컴파일러가 향상됨에 따라 향후 유지 보수 담당자에게 큰 슬픔을 줄 수 있다고 가정합니다.

+0

while 루프에서 준비 됨 읽기를 이동하면 POSIX 표준. –

0

이제 코드가 예상대로 동작합니까, 아니면 작동하도록 준비해야합니까?

이 상황에서 volatile을 사용하는 것이 좋습니다. 이 경우에는 필요하지 않습니다.

IOW, 개인적으로 나는 volatile을 추가하고 잠금을 제거 했으므로 변수 값을 설정하거나 읽는 데 필요하지 않습니다.

다른 컴파일러와 라이브러리가 다르게 처리합니까? 주위에 최적화를 방지하거나 컴파일러가 일반적으로 라운드 함수 호출을 최적화하지 못하게하는 뮤텍스 함수 주위에 무언가가있을 수 있기를 바랍니다. 귀하의 경우

함수 (에 pthread_mutex_lock())에 대한 호출 부작용을 가지며 실행 환경을 변경한다.따라서 컴파일러는 함수 호출에 의해 변경 될 수있는 전역 변수를 다시 읽어야합니다.

정말 확실하기 때문에 C99의 5.1.2.3 Program execution에서 용어를 빌린 곳으로 문의하십시오. 당신에게 맛을 제공합니다 :

[...]는 파이 르를 수정, 개체를 수정, 휘발성 객체를 액세스, 또는 그 작업의 변경 모든 부작용이다 수행하는 함수를 호출 실행 환경의 상태. 표현의 평가는 부작용을 일으킬 수 있습니다. 시퀀스 포인트으로 지정된 실행 시퀀스의 특정 시점에서 이전 평가의 모든 부작용이 완료되고 이후 평가의 부작용이 발생하지 않아야합니다. (시퀀스 포인트의 요약은 부록 C에있다.)

추상 기계에서는 모든 표현식이 의미론에 의해 지정된 것으로 평가된다. 실제 구현은 값이 사용되지 않고 필요한 부작용이 발생하지 않는다고 추론 할 수있는 경우 표현식의 일부를 평가할 필요가 없습니다 (함수를 호출하거나 휘발성 객체에 액세스 한 경우 포함). 인자가 평가 된 후에 함수 호출 -
[...]을 부록 C에서

발췌 :

는 다음 5.1.2.3에 기재된 서열 포인트는 (6.5.2.2).

그리고 거기에서.

제 경험상 컴파일러는 요즘에는 충분히 똑똑하고 적극적으로 최적화 할 때 전역 변수 인 루프 제어 변수로는 아무 것도하지 않을 것입니다. 커널 왕에서

+0

휘발성 키워드를 추가하더라도 잠금 기능이 필요합니다. 이것은 두 가지 이유 때문입니다. 정수를 업데이트하는 것은 원자적일 수 없습니다. 쓰기가 원자 단위 인 경우에도 별도의 캐시가있는 멀티 코어 시스템에서 읽기 및 쓰기가 순서대로 이루어질 것이라는 보장은 없습니다. 명령이 순서대로 수행되도록 보장하는 유일한 방법은 메모리 장벽 명령을 삽입하는 것입니다. 자물쇠는 이것이 확실히 일어나는 것을 보증 할 것입니다. – doron

+0

@ deus-ex-machina399 : 원 자성 정보. 거의 모든 아치는 int보다 작은 또는 동일한 cpu 단어를가집니다. 이는 읽기/쓰기 연산을 원자 적으로 만든다. (증가/감소/등 - 여러 작업을 결합하기 때문에 원자가되지 않습니다 : 읽기, 변경 값, 쓰기). 위와 같이 간단한 읽기/쓰기 코드의 경우 캐시 일관성 보장만으로 충분합니다. http://en.wikipedia.org/wiki/Cache_coherence – Dummy00001

+0

신호를 호출하기 전에 전역 변수 (예 : myval)에 쓰고 다른 스레드가 대기 종료 후 변수를 읽으면 문제가 발생합니다. 메모리 장벽이 없으면 대기 스레드는 읽기 및 쓰기의 순서 변경으로 인해 전역 변수 (myval)가 설정되기 전에 readready를 가져올 수 있습니다. 데이터 메모리 장벽은 이것이 일어나지 않도록합니다. http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/ – doron

1

휘발성이 필요하지 않고 충분한되지도. 그래서 그것을 사용할 이유가 없습니다. 스레드간에 가시성을 제공한다는 표준은 없기 때문에 충분하지 않습니다. pthreads 표준은 뮤텍스가 충분하다고 말하기 때문에 필요하지 않습니다.

더 나쁘다면, 당신이 코드에 마법의 먼지를 뿌려서 작동시키려는 무능한 프로그래머임을 암시하는 것이 좋습니다. 그것은화물 컬트 프로그래밍에 박차를 가하고 코드를 보는 사람은 당신이 그것이 필요하지 않다는 것을 모른다고 추론 할 것입니다. 더 나쁜 것은, 그들은 당신이 충분히 느낀다고 생각할지도 모릅니다. 당신이 작성한 다른 코드에 대해서는 의심 스러울 것입니다. 여러분이 멀티 스레딩 버그를 수정하기보다는 "휘발성"을 사용하여 두려워 할 것을 두려워합니다.

+0

네이티브 POSIX 쓰레드 라이브러리와 같은 pthread 구현이 어떻게 공유 레지스터의 할당 된 공유 변수의 대소 문자를 처리하는지 궁금하다. 컴파일러? –

+0

@ManuelSelva 모든 구현에서 원하는대로 처리 할 수 ​​있습니다. 보통, 당신이해야 할 특별한 것은 없습니다. 다른 스레드가 공유 변수에 액세스 할 수있는 방식으로 다른 컴파일 단위의 함수도이를 액세스 할 수 있으므로 컴파일러는 이미 올바른 작업을 수행합니다. –