2017-03-21 3 views
0

단일 작성기 및 다중 판독기가있는 병렬 코드를 작성하고 있습니다. 작성자는 처음부터 끝까지 배열을 채우고 독자는 배열의 요소에 순서대로 액세스합니다.다중 스레드 단일 작성기 다중 판독기 코드에서 int를 사용하는 것이 안전합니다.

while(!finished){ 
    int myIndex = consumerIndex++; 
    while(myIndex >= producerIndex){ spin(); } 
    use(vec[myIndex]); 
} 

나는 producerIndex 주위 동기화 어떤 종류가 필요하십니까 :

std::vector<Stuff> vec(knownSize); 
int producerIndex = 0; 
std::atomic<int> consumerIndex = 0; 

생산자 스레드 :

for(a while){ 
    vec[producerIndex] = someStuff(); 
    ++producerIndex; 
} 

소비자 스레드 의사 코드는 다음과 같은 것입니다? 일어날 수있는 최악의 상황 인 것처럼 보입니다. 업데이트가 진행되는 동안 오래된 값을 읽으므로 여분의 시간을 돌릴 수 있습니다. 내가 놓친 게 있니? myIndex에 대한 각각의 할당이 고유 할 수 있습니까?

+3

이것은 하나의 스레드에서 읽고 다른 스레드로 쓰는 'producerIndex'에 대한 데이터 경쟁입니다. –

+0

네,하지만 소비자가 오래된 값이나 오래된 값 +1을 읽을 수있는 "호의적 인 경쟁"처럼 보입니다. 둘 다 여기에서 확인이 가능합니다. produceIndex에 실제로 저장되지 않은 값을 읽을 수 있습니까? –

+2

@BenJones 레이스는 정의되지 않은 동작입니다. 그것은 오래된 가치 일 수도 있고 새로운 가치 일 수도 있습니다. 그러나 그것은 또한 wo (새로운 상위 바이트와 오래된 하위 바이트)의 조합 일 수도 있습니다. 아니면 충돌하거나 다른 이상한 물건을 만들 수 있습니다. – Christophe

답변

3

의견에서 지적했듯이이 코드에는 데이터 경쟁이 있습니다. 코드가 원하는대로 할 수 있는지 추측하는 대신에 producerIndexconsumerIndexint에서 std::atomic<int>으로 변경하고 컴파일러 구현 자나 표준 라이브러리 구현 자로 하여금 자신의 작업을 올바르게 수행 할 수 있도록하십시오. 대상 플랫폼.

0

배열이 캐시에 저장되므로 모든 스레드가 캐시에 저장됩니다. 제작자가 배열에 새로운 값을 넣을 때마다 저장소 주소에 더티 비트가 설정되므로 값을 사용하는 다른 모든 스레드가 RAM에서 캐시의 자체 복사본으로 캐시를 검색합니다. 즉, 캐시 미스는 많이 발생하지만 경쟁 조건은 없습니다. :)

+0

이것은 현대 CPU의 작동 방식 (캐시가 작동하고 RAM이 너무 느립니다)이 아니라 C++ 관점에서 차이점을 알 수 없습니다. – MSalters