Alc*_*ott 24 c++ multithreading communication thread-safety visual-c++
我正在使用全局变量实现线程间通信.
//global var
volatile bool is_true = true;
//thread 1
void thread_1()
{
while(1){
int rint = rand() % 10;
if(is_true) {
cout << "thread_1: "<< rint <<endl; //thread_1 prints some stuff
if(rint == 3)
is_true = false; //here, tells thread_2 to start printing stuff
}
}
}
//thread 2
void thread_2()
{
while(1){
int rint = rand() % 10;
if(! is_true) { //if is_true == false
cout << "thread_1: "<< rint <<endl; //thread_2 prints some stuff
if(rint == 7) //7
is_true = true; //here, tells thread_1 to start printing stuff
}
}
}
int main()
{
HANDLE t1 = CreateThread(0,0, thread_1, 0,0,0);
HANDLE t2 = CreateThread(0,0, thread_2, 0,0,0);
Sleep(9999999);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
题
在上面的代码中,我使用全局var volatile bool is_true来切换thread_1和thread_2之间的打印.
我想知道在这里使用赋值操作是否是线程安全的?
Ray*_*hen 59
此代码不保证在Win32上是线程安全的,因为Win32仅为正确对齐的4字节和指针大小的值保证原子性.bool不保证是这些类型之一.(通常是1字节类型.)
对于那些需要一个如何失败的实际例子的人:
假设这bool是一个1字节的类型.假设您的is_true变量恰好存储在另一个bool变量旁边(让我们调用它other_bool),以便它们共享相同的4字节行.具体来说,假设它is_true位于地址0x1000并且other_bool位于地址0x1001.假设两个值都是最初的false,并且一个线程决定is_true在另一个线程尝试更新的同时更新other_bool.可以发生以下操作序列:
is_true到true通过加载包含4字节的值is_true和other_bool.线程1读取0x00000000.other_bool于true通过加载包含4字节的值is_true和other_bool.线程2读取0x00000000.is_true,产生0x00000001.other_bool,产生0x00000100.is_true现在是true和other_bool现在false.is_true现在是false和other_bool现在true.观察到最后这个序列,更新is_true失去了,因为它被线程2覆盖,线程2捕获了旧的值is_true.
碰巧x86非常容忍这种类型的错误,因为它支持字节粒度更新并且具有非常紧凑的内存模型.其他Win32处理器并不宽容.例如,RISC芯片通常不支持字节粒度更新,即使它们存在,它们通常也具有非常弱的内存模型.
不,它不.....你需要使用某种类型的锁定原语.根据平台的不同,您可以使用升级版本,也可以使用本机窗口,例如InterlockedCompareExchange.
实际上在您的情况下,您可能会使用某些线程安全事件机制,以便您可以"发出信号"您的其他线程以开始执行您想要的操作.
| 归档时间: |
|
| 查看次数: |
12409 次 |
| 最近记录: |