我在线程1上有一个向量A,我在线程2上也有一个向量B.
同时写入向量A和B是否安全,因为它们是不同的实例化对象但类型相同?
如果没有,为什么这与在线程1上写入int c和在线程2上写入int d不同?
答案 0 :(得分:3)
标准容器类都不是线程安全的。如果两个不同的线程访问修改共享资源的相同成员函数,那么您的代码就不安全了。
但是在您的代码中,vectorA
和vectorB
不是共享资源,那么您的代码是安全的,假设向量不包含共享资源本身。
答案 1 :(得分:2)
STL容器不是线程安全的。因此,您必须实现自己的同步机制,以便在多线程环境中使用STL。
鉴于上述情况,回答你的问题:
即使另一个线程正在读取或写入同一类型的不同实例,也可以安全地读取和写入一个类型的实例。
例如,给定相同类型的对象A
和B
(在您的情况下为std::vector
),如果在线程1和{{1中写入A
,则是安全的。正在线程2中读取。
为什么在不同的线程上写入两个整数会有所不同?
它是一样的。
就像你不需要任何同步来写两个不同线程中的两个单独的整数一样,你不需要任何同步来写两个不同线程中的两个不同的向量。
以下是来自MSDN的 relevant citation :
以下线程安全规则适用于标准C ++库中的所有类(B
和shared_ptr
类除外),如下所述。
单个对象可以从多个线程读取线程。
例如:给定一个对象iostream
,可以安全地同时从A
和A
阅读thread 1
。如果一个线程正在写入一个对象,则必须保护对相同或其他线程上该对象的所有读写操作。
例如:给定一个对象thread 2
,如果A
写入thread 1
,则必须阻止A
读取或写入thread 2
。即使另一个线程正在读取或写入同一类型的其他实例,也可以安全地读取和写入一个类型的实例。
例如:给定相同类型的对象A
和A
,如果在B
中写入A
并且正在读取thread 1
,则是安全的{1}}。
答案 2 :(得分:1)
我非常希望所有标准容器实现对于非共享集合都是线程安全的(即相同类型的不同集合,就像你所说的那样)。
但是,确切地说,你必须查阅你的库的文档,因为标准根本没有解决线程问题(c ++ 11在那里进行了一些修改,但是实现并没有与之相提并论)< / p>
唯一的边缘情况是一些字符串库实现,特别是io流(主要是因为共享信息,如区域设置定义,字符集和可能延迟构造的句子;主要是风险将是多个线程构建相同的全局数据当你积极操纵和灌输场所方面时,风险会变得更大。)
答案 3 :(得分:1)
有关C ++ 0x FDIS作为C ++ 03的参考文献根本没有提到线程。
首先:是的,在两个不同的线程中使用两个不同的容器(小心通过引用/指针进行别名)是安全的。
§17.6.5.9避免数据竞争
2 / C ++标准库函数不应直接或间接访问除当前线程以外的线程可访问的对象(1.10),除非通过函数的参数直接或间接访问对象,包括此参数。
3 / C ++标准库函数不应直接或间接修改除当前线程以外的线程可访问的对象(1.10),除非通过函数的非const参数直接或间接访问对象,包括此。
(进一步注意到,如果实现使用不同对象之间的共享状态,则应适当保护访问权限以使其对用户不可见)
更重要的是,访问一个容器中的两个不同对象是安全的!
§23.2.2容器数据竞赛
2 /尽管如此(17.6.5.9),当同时修改
vector<bool>
以外的同一序列中不同元素中包含对象的内容时,需要实现以避免数据争用。
此外,即使C ++ 98 / C ++ 03没有在标准中解决这个问题,任何质量的实现都已经符合。如果您使用的是MSVC或gcc的库,它已经可以使用了,它也可能适用于大多数其他编译器的库。
答案 4 :(得分:0)
是的,这很安全。如果线程1分配向量A,并且线程2分配向量B,并且既不知道关于另一个向量实例的任何信息,那么它将是安全的。它与访问int不会有任何不同。
现在,如果线程1和线程2试图访问相同的向量或int,那么这不是线程安全的,你将不得不添加同步。