在两个线程之间共享int时可能会出现什么问题?

时间:2010-04-17 17:20:40

标签: c++

两个线程访问共享的int,x。指令重新排序等会产生什么问题。

主题1:

x = 1;

主题2:

obj.f(x);

如果x是声红外波动,会发生什么变化? 如果线程1和线程2在不同的内核上运行会发生什么变化?

3 个答案:

答案 0 :(得分:3)

  

两个线程访问共享int x。指令重新排序等会产生什么问题。

没有互斥体?不要这样做,否则你将冒着鼻子的危险。 :-)确切地说,任何事情都可能发生。它甚至可能起作用(只要你不依赖于一致的值)。但真的不这样做。

  

如果x为声明volatile,会有什么变化?

不多,或者行为会有所不同,但你仍然没有得到你想要的东西。易失性变量用于处理内存映射设备之类的内容,而不是通过CPU缓存。

  

如果线程1和线程2在不同的内核上运行会发生什么变化?

问题会变得更糟(但你可能也不会立即看到任何差异)。如果没有互斥锁或信号量,您将不会使用任何内存屏障;它们是使事情发挥作用的关键(以及在另一个写入时阻止一个线程读取或写入的正确锁定)并且它们不是标准C ++的全部内容。这就是你使用正确的线程原语的原因;他们为你解决这些尴尬的问题。

请注意,测试保证能够解决线程一致性问题;它们固有地接近竞争条件,发生的事情通常会根据系统负载而变化。

答案 1 :(得分:2)

volatile不适用于c ++中的线程同步,而是避免某些编译器优化(参见:http://en.wikipedia.org/wiki/Volatile_variable

如果需要控制对x的访问,则需要使用互斥锁或原子。

编辑:以下是关于在没有互斥锁的情况下阅读时会发生什么的讨论,即使只有一个整数 - Is it safe to read an integer variable that's being concurrently modified without locking?

答案 2 :(得分:1)

如果不同步线程,x的值可以在线程2的视图中随时更改。

我们来看看:

class A {
public:
   A() { x = 0; }
   void set() { x = 1; }
   int f() { return x + x%2; }
   int x;
};

现在,如果线程1调用set而线程2调用f,而没有同步,则f的结果是未定义的。它可以是0 + 0%2或1 + 0%2或1 + 1%2。

线程运行的内核数量和数量无关紧要。未使用显式线程同步时,未定义执行顺序。