큰 배열 (3e9 요소)의 데이터가 있고 여러 스레드에서 해당 값을 업데이트 중입니다. 방금 경쟁 조건이 있다는 것을 알았습니다.데이터의 일부를 잠금으로 사용할 수 있습니까?
요소가 서로 독립적이므로 전체 기능을 잠글 필요가 없다고 생각하면 과 data[234]
의 업데이트를 동시에 안전하게 수행 할 수 있습니다.
data[]
에있는 각 요소의 최상위 비트가 절대로 사용되지 않을 것입니다. 그 비트에 GCC 기본 내장 잠금을 구현하는 것이 안전합니까?
내 코드는 다음과 같지만 교착 상태가 발생하는 것으로 보입니다.
const unsigned short LOCK_MASK = 1<<15;
unsigned short * lock = &(data[position]);
unsigned short oldLock, newLock;
//lock
do {
oldLock = *lock;
newLock = oldLock^LOCK_MASK;
} while ((oldLock & LOCK_MASK) || !__sync_bool_compare_and_swap(lock, oldLock, newLock));
//update data[position] here
...
...
...
//unlock
*lock ^= LOCK_MASK;
나는 또한이 게시물 (Lightweight spinlocks built from GCC atomic operations?)를 읽고 내 디자인에 내 data
편집에 volatile
을 추가 한, 0 해제 의미하며, 1 수단은 귀하의 코드 번호를 포함
잠금을 획득하기 전에 모든 읽기 작업에 동기화가 필요합니다. 특히,'oldLock = * lock; '은 잘못되었습니다. 원자 적이어야합니다. 그대로,'(oldLock & LOCK_MASK)'가 한 번 true 일 경우 옵티마이 저는'* lock'이 변경되지 않는다고 가정합니다. –
좀 더 보수적 인 접근법은 적절한 수의 실제 뮤텍스 (또는 스핀 록 또는 사용하려는 메커니즘)를 할당하고이를 사용하여 데이터에 대한 액세스를 동기화하는 것입니다. 예 : M 개의 뮤텍스 배열을 가지고 있다면 데이터 배열에 값 #i를 읽거나 쓰기 전에 각 스레드가 뮤텍스 # (i % M)을 잠그도록하십시오. 뮤텍스에 대한 경합이 여전히 받아 들일 정도로 희귀하다는 점에서 가장 작은 값을 찾을 때까지 M의 값을 조정하십시오. –