使用线程对矢量进行排序

时间:2010-03-03 02:48:10

标签: c++ multithreading vector

C ++ STL中定义的向量是重入的还是线程安全的? 我可以使用两个线程并在不使用互斥锁的情况下在矢量的两半上工作(在这种情况下是排序)吗? 例如:

int size = (Data_List.size())/2;

Thread A()
{

................ // Do we need to lock Data_list with a mutex
 sort(Data_List.begin(),Data_List.begin()+size,cmp);
}

Thread B()
{
....// Do we need to lock Data_list with a mutex
sort(Data_List.begin()+(size+1),Data_List.end(),cmp);
}

我的问题是我们是否需要使用互斥锁来锁定Data_List的访问权限?

注意:cmp函数是一个常规的int比较函数。

5 个答案:

答案 0 :(得分:6)

只要线程在不同的内存区域上工作,并且比较函数只适用于那个内存和局部变量,你应该没问题。本质上,你通过划分线程之间的工作来“锁定”表的每一半,并且只让线程处理其一半的数据。

答案 1 :(得分:3)

差不多,但并不完全。这个代码通常不是线程安全的,即使假设实现对向量的线程安全性做出了合理的保证。

假设Data_List::value_type是您的体系结构不提供原子访问的类型。例如,在x86上,字节写入和对齐的字和双字写入是原子的,但是短写不是,并且用户定义类型的写入不是,除非它们碰巧是一个好的大小和对齐。如果您的UDT大小为3,则可能会出现问题。

要执行非原子短写,实现可能会执行两个字节写操作。或者它可能加载单词,修改两个字节,然后将单词写回。在字节写入昂贵的架构上,后者非常合理。

现在,假设你的实现是后者。进一步假设你的向量分割恰好将一个单词的前半部分留在一个部分中,而另一个部分留在另一个部分中。最后假设两个不同的线程都试图同时修改该单词。这可能会出错 - 它们可能都读取相同的值,同时修改它,但是一次写回将发生在另一次之前,因此其中一个修改将被覆盖并丢失。

默认情况下,原子字节访问不是通用的,我怀疑默认情况下任何实现都会进行原子位访问。因此即使其他矢量类型是安全的,vector<bool>也是一个可能的问题:矢量的除法可能会在一个字节的中间。并不是说你通常会以这种方式排序,但是还有其他操作可能会尝试划分向量,或者你的代码可能是通用的。

您通常可以期待单词访问是原子的(在C或C ++中,int访问)。但是语言标准不能保证,因此sig_atomic_t。你说你的cmp是一个int比较函数,这表明你的向量可能包含整数。但你可以使用int比较函数很好地比较短裤,所以我不知道。

您实际需要做的是非常仔细地检查您的实现/平台,并查看从多个线程安全访问内存的内容。它可能适用于int的矢量。

答案 2 :(得分:2)

您可以将GCC的并行模式(如果使用GCC)用于各种算法的线程版本。 http://gcc.gnu.org/onlinedocs/libstdc++/manual/parallel_mode.html

答案 3 :(得分:2)

从技术上讲,标准说这些类不是线程安全的,所以如果你从[]运算符之类的东西设置数据,那么从技术上来说就是在一个对象上多次写入。另一方面,在c阵列的不同部分上操作是安全的...所以这里似乎存在冲突。如果你想要干净利落,请取第一个元素的地址并将其视为一个c-array。这里有很多答案说只要你在数组的不同部分就可以了,虽然在许多实现中这可能都是正确的

- &gt;我认为重要的是要注意一个实现是免费的,不能保证这个安全。

答案 4 :(得分:1)

如果线程处理向量的不相交部分,则不应该有任何问题。