18 Responses

Page 1 of 1
  1. 这周我加星 – 2010年04月23日 : 这周我加星

    [...] 多线程程序中操作的原子性 [...]

  2. dzh
    dzh at · · Reply

    x++可以用汇编来写 : __asm LOCK inc dword ptr[x]
    这样x++只有一条指令。并且是原子操作指令。

  3. 多线程队列的算法优化 | 并行实验室 | Parallel Labs

    [...] 发现玄机了么?是的,dequeue每次返回的不是头节点,而是头节点的下一个节点:如果head->next不为空的话就把这个节点作为返回值,同时在把head指针指向这个节点,此时旧的头节点就可以被free掉了。这个在初始化时插入空节点的tricky使得enqueue和dequeue彻底相互独立了。但是,还是会有一个小地方在实现的时候需要注意,即对第一个空节点的next指针的读写。想象一下,当一个线程对一个空队列进行enqueue操作时刚刚运行完第25行的代码(对该空节点的next指针进行写操作);而此时另一个线程对这个队列进行dequeue操作恰好运行到第33行(对该空节点的next指针进行读操作),它们其实还是有冲突!不过,好在一般来讲next指针是32位数据,而现代的CPU已经能保证多线程程序中32位数据读写操作的原子性,所以这个不是问题。唯一需要注意的是我们要确保enqueue线程是先让要添加的新节点包含好数据再把新节点插入链表(也就是不能先插入空节点,再往节点中填入数据),那么dequeue线程就不会拿到空的节点。 [...]

  4. 关于多线程中操作的原子性 « 我的博客's Blog

    [...] 看到这个题目,觉得还是没有什么把握,到网上搜到一个篇非常详细的文章,很忍不住要转过来,原文地址是:http://www.parallellabs.com/2010/04/15/atomic-operation-in-multithreaded-application/,希望作者不要介意,看到这个作者写博文相当认真,他的博客都是关于并行计算的,地址在这里。此博文详细的介绍了原子性操作的机制,详细的分析解答了此题目。 [...]

  5. 多线程程序常见Bug(上) | 并行实验室 | 并行实验室 | Parallel Labs

    [...] 这个例子的对象是两条语句,所以很容易看出来它们不是原子的。事实上,有些看起来像是原子操作的代码实际上也不是原子的。最著名的莫过于多个线程执行类似“x++”这样的操作了。这条语句本身不是原子的,因为它在大部分硬件平台上其实是由三条语句实现的: [...]

  6. 为什么在多线程程序中要慎用volatile关键字? | 并行实验室 | Parallel Labs

    [...] 这个volatile的acquire和release语义是VS自己的扩展,C/C++标准里是没有的,所以同样的代码用gcc编译执行结果就可能是错的,因为编译器/CPU可能做违反正确性的乱序优化。Acquire和release语义本质上就是为了保证程序执行时memory order的正确性。但是,虽然这个VS扩展使得volatile变量能保证ordering,但是它还是不能保证原子性。volatile g_nCnt++这条语句本身就不是原子操作,volatile跟原子性没有任何关系。想要保证这个操作是原子的,就必须使用带LOCK语义的++操作,也可以看看我这篇文章。 [...]

  7. Jermery
    Jermery at · · Reply

    我们会发现最终x的值会是1而不是2,因为Thread 1的结果被覆盖掉了,博主,这句话不是很明白~~请指教~~
    意思是说t1 t2都对x做了++,期望是2,但结果是1 ?

  8. Richard
    Richard at · · Reply

    Nice. Thanks.

  9. xingchong
    xingchong at · · Reply

    很不错的文章; 早点看到会跟好;
    之前调过一个bug; 相邻的两个bitfield用了两把锁分别保护, 结果就悲剧了;

  10. andy xie
    andy xie at · · Reply

    关于第二个问题“2. 对Bit field(位域)的读写操作是否是线程安全的?”,有点疑问。第二个问题中给出的例子,到底出现什么情况才会出现线程不安全,能不能给具体解释一下。

    1. Tony Jin
      Tony Jin at · · Reply

      假设位域是:
      struct foo {
      int flag : 1;
      int counter : 15;
      };
      对flag或者counter的读写并不是一个单独的指令就能完成的,而是要经过很多个步骤,才能从一个字(16位)里面解析出flag和counter,计算过程中需要寄存器作为中间值,如果多个线程同时做访问,必然会导致数据的混乱,可以写如下代码,然后反汇编看看就知道了:
      foo f;
      f.flag = 1;
      f.counter = 1;
      GoodLuck:)

  11. mordorw
    mordorw at · · Reply

    x++如果有三条指令,你用硬件的lock前缀搞的定么?恐怕要用软件锁了

    单个指令也无法保证原子性,单个指令才用硬件的lock前缀搞定

    x++可以用汇编来写 : __asm LOCK inc dword ptr[x]
    这样x++只有一条指令。并且是原子操作指令

  12. Tony Jin
    Tony Jin at · · Reply

    你好,你的这篇文章让我获益匪浅,但有以个疑问:
    16-bit accesses to uncached memory locations that fit within a 32-bit data bus(未缓存且在32位数据总线范围之内的内存地址的访问)
    我的理解是假设有一个地址X是32位对齐的,那么如果我要访问X+8~X+24,这16位的数据,虽然X+8不是16位对齐的,但没有越过这个32位边界,所以是有原子保证的,请问我的理解是否正确?如果不正确,能否说明一下,感谢万分:)

Leave a Reply