C++ 在两个线程之间共享int时可能会出现什么问题?
两个线程访问一个共享int,x。指令重新排序等会产生什么问题 线程1:C++ 在两个线程之间共享int时可能会出现什么问题?,c++,C++,两个线程访问一个共享int,x。指令重新排序等会产生什么问题 线程1: x = 1; 线程2: obj.f(x); 如果x是不稳定的,会发生什么变化? 如果线程1和线程2在不同的内核上运行,会发生什么变化?如果不同步线程,则在线程2的视图中,x的值可以随时更改 让我们看看: class A { public: A() { x = 0; } void set() { x = 1; } int f() { return x + x%2; } int x; }; 现在,如
x = 1;
线程2:
obj.f(x);
如果x是不稳定的,会发生什么变化?如果线程1和线程2在不同的内核上运行,会发生什么变化?如果不同步线程,则在线程2的视图中,x的值可以随时更改 让我们看看:
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
线程运行的核心是什么或有多少并不重要。未使用显式线程同步时,未定义执行顺序。如果不同步线程,则在线程2的视图中,x的值可以随时更改 让我们看看:
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
线程运行的核心是什么或有多少并不重要。不使用显式线程同步化的情况下,不执行执行顺序。 <代码>代码> Value<代码>不是用于C++中的线程同步,而是为了避免某些编译器优化(参见:)/P> 如果您需要控制对x的访问,则需要使用互斥或原子
<> > >编辑:这里讨论了在没有互斥体的情况下发生的事情,即使只是一个int -< /p> < > >代码> < <代码> >,并不意味着C++中的线程同步,而是避免某些编译器优化(参见:) 如果您需要控制对x的访问,则需要使用互斥或原子 编辑:这里讨论了在没有互斥锁的情况下阅读时会发生什么,即使只有int- 两个线程访问一个共享int,
x
。指令重新排序等会产生什么问题
没有互斥?不要那样做,否则你将冒着鼻魔的危险。:-)确切地说,任何事情都可能发生。它甚至可能看起来有效(只要您不依赖一致的值)。但真的不要那样做
如果x
声明为红色volatile
,会发生什么变化
不会太多,或者可能行为会有所不同,但你仍然得不到你想要的东西。易失性变量用于处理内存映射设备之类的事情,而不是欺骗您通过CPU缓存
如果线程1和线程2在不同的内核上运行,会发生什么变化
问题会变得更糟(但您可能也不会立即看到任何差异)。如果没有互斥或信号量,就不会使用任何内存障碍;它们是使事情起作用的关键(同时还有一个适当的锁来阻止一个线程在另一个写的时候读或写),它们根本不属于标准C++。这就是为什么要使用正确的线程原语;他们为你解决这些棘手的问题
请注意,测试不能保证发现线程一致性问题;它们本质上接近比赛条件,发生的情况通常会根据系统负载而变化
两个线程访问一个共享int,x
。指令重新排序等会产生什么问题
没有互斥?不要那样做,否则你将冒着鼻魔的危险。:-)确切地说,任何事情都可能发生。它甚至可能看起来有效(只要您不依赖一致的值)。但真的不要那样做
如果x
声明为红色volatile
,会发生什么变化
不会太多,或者可能行为会有所不同,但你仍然得不到你想要的东西。易失性变量用于处理内存映射设备之类的事情,而不是欺骗您通过CPU缓存
如果线程1和线程2在不同的内核上运行,会发生什么变化
问题会变得更糟(但您可能也不会立即看到任何差异)。如果没有互斥或信号量,就不会使用任何内存障碍;它们是使事情起作用的关键(同时还有一个适当的锁来阻止一个线程在另一个写的时候读或写),它们根本不属于标准C++。这就是为什么要使用正确的线程原语;他们为你解决这些棘手的问题
请注意,测试不能保证发现线程一致性问题;它们本质上接近竞赛条件,发生的情况通常会根据系统负载而变化。我猜您的意思是,如果f将参数作为参考-f(int&value)?如果f被声明为f(int值),x将被复制到堆栈…@Tobbe-No。他试图解释x的值在线程2中是未知的,因为还不能保证它被设置为1。好的,这是一个竞争条件的示例。我实际上是指在单次写入(线程1)和单次读取(线程2)过程中可能出现的错误。但这可能不是很清楚……我猜你的意思是,如果f将参数作为参考-f(int&value)?如果f被声明为f(int值),x将被复制到堆栈…@Tobbe-No。他试图解释x的值在线程2中是未知的,因为还不能保证它被设置为1。好的,这是一个竞争条件的示例。我实际上是指在单次写入(线程1)和单次读取(线程2)过程中可能出现的错误。但这可能不是很清楚…原子或互斥是解决方案。但问题是如果我不保护变量会发生什么?你会得到未定义的行为。如果在修改x的同时读取线程2,那么最终会看到什么,这实际上是一个特定于平台的问题。原子或互斥是解决方案。但问题是如果我不保护变量会发生什么?你会得到未定义的行为。结果真的是