• <legend id='02Qv2'><style id='02Qv2'><dir id='02Qv2'><q id='02Qv2'></q></dir></style></legend>
    <i id='02Qv2'><tr id='02Qv2'><dt id='02Qv2'><q id='02Qv2'><span id='02Qv2'><b id='02Qv2'><form id='02Qv2'><ins id='02Qv2'></ins><ul id='02Qv2'></ul><sub id='02Qv2'></sub></form><legend id='02Qv2'></legend><bdo id='02Qv2'><pre id='02Qv2'><center id='02Qv2'></center></pre></bdo></b><th id='02Qv2'></th></span></q></dt></tr></i><div id='02Qv2'><tfoot id='02Qv2'></tfoot><dl id='02Qv2'><fieldset id='02Qv2'></fieldset></dl></div>

      <small id='02Qv2'></small><noframes id='02Qv2'>

      • <bdo id='02Qv2'></bdo><ul id='02Qv2'></ul>
      <tfoot id='02Qv2'></tfoot>
      1. 赋值运算符“="是原子的吗?

        时间:2023-10-06
        <i id='XwCY1'><tr id='XwCY1'><dt id='XwCY1'><q id='XwCY1'><span id='XwCY1'><b id='XwCY1'><form id='XwCY1'><ins id='XwCY1'></ins><ul id='XwCY1'></ul><sub id='XwCY1'></sub></form><legend id='XwCY1'></legend><bdo id='XwCY1'><pre id='XwCY1'><center id='XwCY1'></center></pre></bdo></b><th id='XwCY1'></th></span></q></dt></tr></i><div id='XwCY1'><tfoot id='XwCY1'></tfoot><dl id='XwCY1'><fieldset id='XwCY1'></fieldset></dl></div>

          <tbody id='XwCY1'></tbody>
        <legend id='XwCY1'><style id='XwCY1'><dir id='XwCY1'><q id='XwCY1'></q></dir></style></legend>

        <small id='XwCY1'></small><noframes id='XwCY1'>

              <bdo id='XwCY1'></bdo><ul id='XwCY1'></ul>
            • <tfoot id='XwCY1'></tfoot>
                  本文介绍了赋值运算符“="是原子的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我正在使用全局变量实现线程间通信.

                  //全局变量volatile bool is_true = true;//线程1无效线程_1(){而(1){int rint = rand() % 10;如果(is_true){cout<<线程_1:"<<rint<<endl;//thread_1 打印一些东西如果(rint == 3)is_true = false;//这里,告诉thread_2开始打印东西}}}//线程2void thread_2(){而(1){int rint = rand() % 10;if(!is_true) {//if is_true == falsecout<<线程_1:"<<rint<<endl;//thread_2 打印一些东西if(rint == 7)//7is_true = 真;//这里,告诉thread_1开始打印东西}}}int main(){处理 t1 = CreateThread(0,0, thread_1, 0,0,0);处理 t2 = CreateThread(0,0, thread_2, 0,0,0);睡眠(9999999);返回0;}

                  问题

                  在上面的代码中,我使用全局变量 volatile bool is_true 在 thread_1 和 thread_2 之间切换打印.

                  不知道在这里使用赋值操作是否线程安全?

                  解决方案

                  此代码不保证在 Win32 上是线程安全的,因为 Win32 仅保证正确对齐的 4 字节和指针大小的值的原子性.bool 不能保证是这些类型之一.(通常是 1 字节类型.)

                  对于那些需要一个实际例子来说明这可能会失败的人:

                  假设 bool 是一个 1 字节的类型.还假设您的 is_true 变量恰好与另一个 bool 变量相邻存储(我们称其为 other_bool),以便它们共享相同的 4 字节行.为了具体起见,假设 is_true 在地址 0x1000 处,other_bool 在地址 0x1001 处.假设两个值最初都是false,并且一个线程决定更新is_true,同时另一个线程尝试更新other_bool.可能会发生以下操作序列:

                  • 线程 1 准备通过加载包含 is_trueother_bool 的 4 字节值将 is_true 设置为 true.线程 1 读取 0x00000000.
                  • 线程 2 准备通过加载包含 is_trueother_bool 的 4 字节值将 other_bool 设置为 true.线程 2 读取 0x00000000.
                  • 线程 1 更新对应于 is_true 的 4 字节值中的字节,产生 0x00000001.
                  • 线程 2 更新对应于 other_bool 的 4 字节值中的字节,产生 0x00000100.
                  • 线程 1 将更新后的值存储到内存中.is_true 现在是 trueother_bool 现在是 false.
                  • 线程 2 将更新后的值存储到内存中.is_true 现在是 falseother_bool 现在是 true.

                  观察到在这个序列的最后,对 is_true 的更新丢失了,因为它被线程 2 覆盖,它捕获了 is_true 的旧值.

                  碰巧 x86 对此类错误非常宽容,因为它支持字节粒度更新并且具有非常紧凑的内存模型.其他 Win32 处理器则没有那么宽容.例如,RISC 芯片通常不支持字节粒度更新,即使支持,它们的内存模型通常也很弱.

                  I'm implementing Inter-Thread Communication using global variable.

                  //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;
                  }
                  

                  Question

                  In the code above, I use a global var volatile bool is_true to switch printing between thread_1 and thread_2.

                  I wonder whether it is thread-safe to use assignment operation here?

                  解决方案

                  This code is not guaranteed to be thread-safe on Win32, since Win32 guarantees atomicity only for properly-aligned 4-byte and pointer-sized values. bool is not guaranteed to be one of those types. (It is typically a 1-byte type.)

                  For those who demand an actual example of how this could fail:

                  Suppose that bool is a 1-byte type. Suppose also that your is_true variable happens to be stored adjacent to another bool variable (let's call it other_bool), so that both of them share the same 4-byte line. For concreteness, let's say that is_true is at address 0x1000 and other_bool is at address 0x1001. Suppose that both values are initially false, and one thread decides to update is_true at the same time another thread tries to update other_bool. The following sequence of operations can occur:

                  • Thread 1 prepares to set is_true to true by loading the 4-byte value containing is_true and other_bool. Thread 1 reads 0x00000000.
                  • Thread 2 prepares to set other_bool to true by loading the 4-byte value containing is_true and other_bool. Thread 2 reads 0x00000000.
                  • Thread 1 updates the byte in the 4-byte value corresponding to is_true, producing 0x00000001.
                  • Thread 2 updates the byte in the 4-byte value corresponding to other_bool, producing 0x00000100.
                  • Thread 1 stores the updated value to memory. is_true is now true and other_bool is now false.
                  • Thread 2 stores the updated value to memory. is_true is now false and other_bool is now true.

                  Observe that at the end this sequence, the update to is_true was lost, because it was overwritten by thread 2, which captured an old value of is_true.

                  It so happens that x86 is very forgiving of this type of error because it supports byte-granular updates and has a very tight memory model. Other Win32 processors are not as forgiving. RISC chips, for example, often do not support byte-granular updates, and even if they do, they usually have very weak memory models.

                  这篇关于赋值运算符“="是原子的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:如何判断一个库是用/mt 还是/md 编译的? 下一篇:如何迭代常量向量?

                  相关文章

                  最新文章

                      <bdo id='0lGod'></bdo><ul id='0lGod'></ul>

                      <small id='0lGod'></small><noframes id='0lGod'>

                      <i id='0lGod'><tr id='0lGod'><dt id='0lGod'><q id='0lGod'><span id='0lGod'><b id='0lGod'><form id='0lGod'><ins id='0lGod'></ins><ul id='0lGod'></ul><sub id='0lGod'></sub></form><legend id='0lGod'></legend><bdo id='0lGod'><pre id='0lGod'><center id='0lGod'></center></pre></bdo></b><th id='0lGod'></th></span></q></dt></tr></i><div id='0lGod'><tfoot id='0lGod'></tfoot><dl id='0lGod'><fieldset id='0lGod'></fieldset></dl></div>

                      <legend id='0lGod'><style id='0lGod'><dir id='0lGod'><q id='0lGod'></q></dir></style></legend>
                    1. <tfoot id='0lGod'></tfoot>