听说有人说 var++ 和 ++var 之类的语句不是线程安全的,所以我写了一个应用程序进行测试。代码如下:
unsigned long gCounter = 0;
const unsigned long WORKS = 1048576; // pow(2, 20)
const unsigned long MAX_THREADS = 100;
const unsigned long WORKER_THREADS = 2;
unsigned long GetCounter(){
return gCounter++;
}
void *WorkerThread(void *){
unsigned long items = 0;
do {
GetCounter();
items++;
} while(items < WORKS);
printf("Exiting thread: %lu\n", pthread_self());
return NULL;
}
int main(int argc, char* argv[]){
pthread_t workers[MAX_THREADS];
//create two threads
for (int i = 0; i < WORKER_THREADS; i++){
pthread_create(&workers[i], NULL, WorkerThread, NULL);
}
//wait for above threads to exit
for (int i = 0; i < WORKER_THREADS; i++){
pthread_join(workers[i], NULL);
}
assert( gCounter == (WORKER_THREADS * WORKS));
return 0;
}
如果后增量操作不是线程安全的,那么上面的测试应用程序有时会失败(可能会成功)。但令我惊讶的是,在我们的服务器上运行时,它在 200 次测试中总是成功,而在我的 PC 上它从未成功。
为什么会发生这种情况?为什么上面的应用程序会在我们的服务器上一直成功?以下是有关服务器和我的 PC 的信息:
Server machine:
System: Redhat 3.4.2 - 6.FC3 Kernel: LINUX.2.6.10
GCC Version: 3.4.2 20041017
CPU: AMD Opteron Processor 144 X86_64
My PC:
System: ubuntu 3.2.0-40-generic Kernel: LINUX.3.4
GCC Version: 4.6.3 (Ubuntu/Linaro )
CPU: Intel(R) Pentium(R) Dual CPU T2370
Build Command (both are the same, turn off optimization)
g++ -O0 -o test test.cpp -lpthread
更新
今天我发现CPU是AMD Opteron 144的服务器是单CPU单核机器,也许这就是这个测试应用程序永远不会失败的原因。据我了解,单CPU单核机器不支持真正的线程并行,线程以非常快的速度运行,它们似乎并行运行,但实际上并非如此,一些线程同步问题不是在这种机器上很容易发生。