최근 샘플 코드가 있습니다 (실제 코드는 훨씬 복잡합니다). 한스 보엠 (Hans Boehm)의 cppcon16이 원자 적으로 얘기하는 것을 본 후, 나는 코드가 작동하는지 조금 걱정된다.원자 단위를 사용하여 단일 프리 프로듀서 다중 소비자 데이터 구조체를 잠급니다.
produce
은 단일 제작자 스레드에 의해 호출되고 consume
은 다중 소비자 스레드에 의해 호출됩니다. 생산자는 2, 4, 6, 8, ...과 같은 순차 번호의 데이터 만 업데이트하지만 데이터가 더럽다는 것을 나타 내기 위해 데이터를 업데이트하기 전에 1, 3, 5, 7 등과 같은 홀수 시퀀스 번호로 설정합니다. 소비자는 동일한 순서 (2, 4, 6, ...)로 데이터를 가져 오려고합니다.
소비자는 데이터가 양호한 지 확인하기 위해 읽은 다음 시퀀스 num을 확인합니다 (읽는 동안 생산자가 업데이트하지 않음).
x86_64가 다른 상점의 상점을 다시 정렬하지 않거나 상점이나로드로 인해로드되지 않기 때문에 내 코드가 x86_64 (내 대상 플랫폼)에서 잘 작동한다고 생각하지만 다른 플랫폼에서는 잘못된 것 같습니다.
소비자가 손상된 데이터를 읽지 만 여전히 t == t2
이 성공할 수 있도록 데이터 생성 (생산 중)을 위의 '저장 (n-1)'로 이동할 수 있다고 수정합니까? 86을 대상으로 할 때 컴파일러는 C++ 추상 기계,되지 않은 강력한 아키텍처에 의존하는 행동 프로그램의 동작을 유지하기 위해 최적화 때문에
struct S
{
atomic<int64_t> seq;
// data members of primitive type int, double etc
...
};
S s;
void produce(int64_t n, ...) // ... for above data members
{
s.seq.store(n-1, std::memory_order_release); // indicates it's working on data members
// assign data members of s
...
s.seq.store(n, std::memory_order_release); // complete updating
}
bool consume(int64_t n, ...) // ... for interested fields passed as reference
{
auto t = s.load(std::memory_order_acquire);
if (t == n)
{
// read fields
...
auto t2 = s.load(std::memory_order_acquire);
if (t == t2)
return true;
}
return false;
}
주의 사항 : 이와 같은 잠금 장치가없는 구조는 올바르게 구현하기가 어렵습니다. 많은 함정이 있습니다. http://blog.memsql.com/common-pitfalls-in-writing-lock-free-algorithms/ –
http://en.cppreference.com/w/cpp/atomic/memory_order#Release - Aququire_ordering은이 질문을 정확하게 처리합니다. 그것은 당신을 위해 그것을 대답합니까? –
마이클, cppref 링크는 제 질문과 매우 다릅니다. 내가 해결하려고하는 문제는 제작자가 동일한 'S'를 업데이트한다는 것입니다. 여러 번, 나는 생산자가 더 높은 seq no로 데이터를 업데이트하지 않으면 소비자가 지정된 시퀀스 번호의 데이터를 읽도록하고 싶다. – Derek