找回密码
 FreeOZ用户注册
查看: 2424|回复: 14
打印 上一主题 下一主题

[学习深造] C++ atom question

[复制链接]
跳转到指定楼层
1#
发表于 30-6-2016 20:34:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
I don't understand why z.load() show value 2.

Can you explain the idea to me?

Thanks in advance

makefile
default: hello

hello: main.cpp makefile
        g++ -std=c++11 -Wpedantic -Wall -O3 -g -lrt main.cpp -o hello -pthread -Wl,--no-as-needed

main.cpp source code
<atomic>
#include <thread>
#include <iostream>
#include <assert.h>

std::atomic<bool> x,y;
std::atomic<int> z;

void
write_x()
{
        x.store(true, std::memory_order_release);
}

void
write_y()
{
        y.store(true, std::memory_order_release);
}

void
read_x_then_y()
{
        while (!x.load(std::memory_order_acquire));
   
        if (y.load(std::memory_order_acquire)) {
                ++z;
        }
}

void
read_y_then_x()
{
        while (!y.load(std::memory_order_acquire));
   
        if (x.load(std::memory_order_acquire)) {
                ++z;
        }
}

int
main()
{
        x = false;
        y = false;
        z = 0;
   
        std::thread a(write_x);
        std::thread b(write_y);
        std::thread c(read_x_then_y);
        std::thread d(read_y_then_x);
   
        a.join();
        b.join();
        c.join();
        d.join();
   
        std::cout << z.load() << std::endl;
        assert(z.load() != 0);
        //assert(z.load()==0);
}
回复  

使用道具 举报

2#
发表于 30-6-2016 23:58:16 | 只看该作者
因为x和y都是true,所以++z执行了两次?
回复  

使用道具 举报

3#
 楼主| 发表于 1-7-2016 07:28:58 | 只看该作者
clarkli 发表于 30-6-2016 22:58
因为x和y都是true,所以++z执行了两次?

They are running in multiple threads, the order is not controlled. If they are running in single thread or main thread, it is easy to understand the logic.
回复  

使用道具 举报

4#
发表于 1-7-2016 22:17:14 | 只看该作者
DDD888 发表于 1-7-2016 06:28
They are running in multiple threads, the order is not controlled. If they are running in single t ...

所以看缘分,我在VM里面跑的结果大部分是1,偶尔是2
回复  

使用道具 举报

5#
 楼主| 发表于 2-7-2016 07:13:21 | 只看该作者
clarkli 发表于 1-7-2016 21:17
所以看缘分,我在VM里面跑的结果大部分是1,偶尔是2

That is strange. I always got 2
回复  

使用道具 举报

6#
发表于 2-7-2016 13:41:35 | 只看该作者
和操作系统线程调度有关。
换台电脑,或者换个系统结果可能就不一样了。这个代码是不能在生产中用的
回复  

使用道具 举报

7#
 楼主| 发表于 2-7-2016 17:12:57 | 只看该作者
本帖最后由 DDD888 于 2-7-2016 16:26 编辑
clarkli 发表于 2-7-2016 12:41
和操作系统线程调度有关。
换台电脑,或者换个系统结果可能就不一样了。这个代码是不能在生产中用的


The trouble for me is that I do not understand that source code.

I understand following code
#include <atomic>
#include <thread>
#include <iostream>
#include <assert.h>

std::atomic<int> data[5];
std::atomic<bool> sync1(false), sync2(false);

void
thread_1()
{
        data[0].store(42, std::memory_order_relaxed);
        data[1].store(97, std::memory_order_relaxed);
        data[2].store(17, std::memory_order_relaxed);
        data[3].store(-141, std::memory_order_relaxed);
        data[4].store(2003, std::memory_order_relaxed);
   
        sync1.store(true, std::memory_order_release);
}

void
thread_2()
{
        while(!sync1.load(std::memory_order_acquire));

        sync2.store(true,std::memory_order_release);
}

void
thread_3()
{
        while(!sync2.load(std::memory_order_acquire));

        assert(data[0].load(std::memory_order_relaxed) == 42);
        assert(data[1].load(std::memory_order_relaxed) == 97);
        assert(data[2].load(std::memory_order_relaxed) == 17);
        assert(data[3].load(std::memory_order_relaxed) == -141);
        assert(data[4].load(std::memory_order_relaxed) == 2003);
}

int
main()
{
        std::thread a(thread_1);
        std::thread b(thread_2);
        std::thread c(thread_3);

        a.join();
        b.join();
        c.join();
}
回复  

使用道具 举报

8#
发表于 3-7-2016 19:45:23 | 只看该作者
DDD888 发表于 2-7-2016 16:12
The trouble for me is that I do not understand that source code.

I understand following code  ...

不理解为什么输出2还是不理解为什么那样写?
回复  

使用道具 举报

9#
 楼主| 发表于 3-7-2016 19:54:29 | 只看该作者
clarkli 发表于 3-7-2016 18:45
不理解为什么输出2还是不理解为什么那样写?

不理解为什么输出2
回复  

使用道具 举报

10#
发表于 4-7-2016 00:13:00 | 只看该作者
DDD888 发表于 3-7-2016 18:54
不理解为什么输出2

执行顺序可能是:
write_x(); // x is now true
write_y(); // y is now true
read_x_then_y(); // x and y are both true; execute '++z'
read_y_then_x(); // x and y are both true; execute '++z'
回复  

使用道具 举报

11#
 楼主| 发表于 4-7-2016 10:08:51 | 只看该作者
clarkli 发表于 3-7-2016 23:13
执行顺序可能是:
write_x(); // x is now true
write_y(); // y is now true

Thanks

But that is a possibility which I am sure can happen. My question is what must happen. Can it be 0?
回复  

使用道具 举报

12#
发表于 4-7-2016 22:11:19 | 只看该作者
不会,++z至少会被执行一次
回复  

使用道具 举报

13#
 楼主| 发表于 5-7-2016 09:20:05 | 只看该作者
clarkli 发表于 4-7-2016 21:11
不会,++z至少会被执行一次

Why?
回复  

使用道具 举报

14#
发表于 5-7-2016 21:08:45 | 只看该作者
以read_x_then_y()为例

  1. while (!x.load(std::memory_order_acquire));
  2.    
  3. if (y.load(std::memory_order_acquire)) {
  4.     ++z;
  5. }
复制代码

++z不被执行的唯一可能情况是x == true && y == false,而一旦x为true,read_y_then_x()中的++z就必然会被执行。因此++z至少被执行一次。
回复  

使用道具 举报

15#
 楼主| 发表于 6-7-2016 07:10:22 | 只看该作者
clarkli 发表于 5-7-2016 20:08
以read_x_then_y()为例

++z不被执行的唯一可能情况是x == true && y == false,而一旦x为true,read_y_t ...

Thanks for your answer. I understand it now.
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+11, 16-2-2025 21:16 , Processed in 0.024066 second(s), 29 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表