Oracle Solaris Studio 12.2:线程分析器用户指南

2.6.2 用于检验数组值类型的程序

一组线程同时调用 check_bad_array() 以检查数组 data_array 中是否存在任何“错误”元素。每个线程检查数组的不同部分。如果线程发现某个元素有错误,它会将全局共享变量 is_bad 的值设置为真。

20  volatile int is_bad = 0;
 ...

 100  /* 
 101   * Each thread checks its assigned portion of data_array, and sets 
 102   * the global flag is_bad to 1 once it finds a bad data element.
 103   */
 104  void check_bad_array(volatile data_t *data_array, unsigned int thread_id)    
 105  {
 106     int i;
 107     for (i=my_start(thread_id); i<my_end(thread_id); i++) {
 108          if (is_bad) 
 109              return;
 110          else {
 111              if (is_bad_element(data_array[i])) { 
 112                  is_bad = 1;
 113                  return;
 114              }
 115          }
 116     }
 117  }

第 108 行中对 is_bad 的读取与第 112 行中对 is_bad 的写入之间存在数据争用。但是,该数据争用不影响最终结果的正确性。

is_bad 的初始值为 0。当线程更新 is_bad 时,它们会为其分配值 1。也就是说,这些线程会在 is_bad 的同一内存字节的同一位中存储 1。在当前的体系结构中,可以放心地认为这些存储是原子操作。因此,某个线程读取 is_bad 时,读取的值要么为 0,要么为 1。如果某个线程在 is_bad(第 108 行)被分配值 1 之前对其进行检查,则该线程会继续执行 for 循环。在此期间,如果另一个线程也将值 1 分配给 is_bad(第 112 行),这并不会改变最终结果。这仅仅意味着该线程执行 for 循环的时间超出了必要时间。