-1
std::deque<T> dq;
Thread_function(pointer to queue as argument)     // created 8 threads
{
     vertext_found = true;
     **v is initialized to NULL
     while ( i < dq->size())
     {
          EnterCriticalSection(&h);
          if( i < dq.size() ) {
              v = dq.at(i);      // accessing element of queue without popping
              i++;
              vertext_found = true;
          }
          LeaveCriticalSection(&h);
          if (vertext_found && (i < dq.size()) && v != NULL)
          {
              **operation on 'v'
              vertext_found = false;
          }
     }
}

这是否会成为数据竞争条件,尤其是在关键部分之外处理“ while (i < dq->size()) ”时?我的方法正确吗?否则请建议我。

4

1 回答 1

4

这在多线程环境中会不会产生干扰?

在您的问题文本中,dq(就像您的函数中的所有其他变量一样)是一个本地对象:

std::deque<T> dq;

如果确实如此,那么这个问题有一个简单的答案:“是”。它是线程安全的,因为没有争用:每个线程都在一个本地对象上工作,并且由于没有共享,所以不会有任何数据竞争。


现在假设您的代码旨在显示共享数据结构的使用,并且这dq实际上是一个全局对象或多个线程可以同时访问的东西(这dq->size()似乎是函数调用所暗示的),那么答案是“这取决于”

如果您的所有线程仅同时执行您正在显示的函数,并且dq是对 的引用或指针const,因此您的函数不包含对任何非const成员函数的任何调用,那么答案是“是的,你不在这种情况下,根本不需要任何关键部分”。C++11 标准的第 17 段 6.5.9/3 规定:

C++ 标准库函数不得直接或间接修改可由当前线程以外的线程访问的对象 (1.10),除非这些对象是通过函数的非const 参数直接或间接访问的,包括this.

对定义什么是数据竞争的第 1.10 段(尤其是 1.10/21)的引用使上述段落的含义更加清晰:

如果程序的执行在不同的线程中包含两个相互冲突的操作,则该程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。[...]

最后,第 1.10/4 段指定了两个动作何时发生冲突:

如果其中一个修改了内存位置 (1.7) 而另一个访问或修改了相同的内存位置,则两个表达式求值会发生冲突。

所有这一切的结果是const成员函数必须是线程安全的。您可能有兴趣观看Herb Sutter关于它的演示文稿。

由于deque<T>::size()const成员函数,并且at()是返回对 的引用的const成员函数(因为您是从引用或指向的指针调用它) ,因此无需同步来自多个线程的访问。constconst


如果您dq不是的引用或指针const,那么答案是“”,因为at()它是一个非const成员函数。此外,由于v是对元素的非常量引用,因此您的“操作v”可能是非,因此在元素上而不是在其自身const上引入数据竞争。dqdq

同样,如果您的线程同时dq通过其他函数访问和修改,那么答案又是“否”,因为您没有保护对共享对象的所有访问。读操作与写操作冲突(见上文),您只是保护其中的一部分。在这种情况下,您的关键部分应该跨越整个while周期。

于 2013-03-10T18:10:13.150 回答