c++ - 为什么这个测试应用程序在不同的机器上给出不同的结果? (关于后增量和线程安全)

标签 c++ linux multithreading gcc thread-safety

听说有人说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单核机器不支持真正的线程并行,线程以非常快的速度有序运行,它们似乎并行运行,但实际上不是,一些线程同步问题不是在这种机器上很容易发生。

最佳答案

您的代码具有未定义的行为,因为它包含数据竞争。

[intro.multithread]/21 The execution of a program contains a data race if it contains two conflicting actions in dierent threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.

[intro.multithread]/4 Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.

由于您的代码具有未定义的行为,因此您不能依赖它具有任何特定行为。不要惊讶它总是在一个平台上“有效”而在另一个平台上永远无效。

[defns.undefined] Undefined Behavior: Behavior for which this International Standard imposes no requirements.

关于c++ - 为什么这个测试应用程序在不同的机器上给出不同的结果? (关于后增量和线程安全),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16847929/

相关文章:

C++-BGL : sort edges

c++ - C++中数组的动态大小?

Visual Studio 2012 : LPCWSTR and wstring 中的 C++ 编译错误

Android 模拟器 2.0 工具栏在 linux (KDE) 中不可点击

java - 使用java在android中创建简单的线程?

安卓NDK : How to get a Class Loader With a NativeActivity and native_app_glue?

linux - 为什么docker备份数据量时提示 "Permission denied"?

c++ - 如何编译并运行一个hello world JUCE程序?

c# - 优雅地关闭线程

c++ - 线程安全、无数据争用、无滞后共享容器 (circular_buffer)