最近の仕事で、マルチスレッド プログラムにカウンターを実装したいと考えています。私の GCC (3.4.5) には、atomic_tという名前のユーザー空間データ型があることがわかりました。しかし、それは本当のアトミックではないようです。
12コアのx86_64マシンでatomic_inc()/atomic_read()をテストしました.Linuxカーネルは2.6.9です。
これがデモです。pthread_cond_t と pthread_cond_broadcast を追加して、並行性の度合いを高めます。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>
#include <asm/atomic.h>
atomic_t atomic_count;
pthread_cond_t g_cond;
pthread_mutex_t g_mutex;
void* thread_func(void*p) {
pthread_mutex_t* lock = (pthread_mutex_t*)p;
pthread_mutex_lock(lock);
pthread_cond_wait(&g_cond, lock);
pthread_mutex_unlock(lock);
for (int i=0;i<20000;++i){
atomic_inc(&atomic_count);
}
return NULL;
}
#define THRD_NUM 15
int main() {
atomic_set(&atomic_count, 0);
pthread_cond_init(&g_cond, NULL);
pthread_mutex_init(&g_mutex, NULL);
pthread_t pid[THRD_NUM];
for (int i=0; i<THRD_NUM; i++) {
pthread_create(&pid[i], NULL, thread_func, &g_mutex);
}
sleep(3);
pthread_cond_broadcast(&g_cond);
for (int i=0; i<THRD_NUM; i++) {
pthread_join(pid[i], NULL);
}
long ans = atomic_read(&atomic_count);
printf("atomic_count:%ld \n", ans);
}
期待される結果は 300000 ですが、代わりに常に 270000+ または 280000+ が得られます。私は、atomic_inc()の実装が
static __inline__ void atomic_inc(atomic_t *v)
{
__asm__ __volatile__(
LOCK "incl %0"
:"=m" (v->counter)
:"m" (v->counter));
}
インテルのマニュアルによると、LOCKプレフィックスにはフル バリアの意味があります。それは、プログラムの出力が命令の並べ替えとは何の関係もないということですか?
さらに、興味深い現象を発見しました。THRD_NUMを 12 (マシンのコア番号) 未満に設定すると、エラーの頻度が低くなります。コンテキストスイッチが原因である可能性があると思います。しかし、これがどのように起こったのかわかりません。誰かが私を助けることができますか?ありがとう!