gpt4 book ai didi

c++ - 将 std::atomic_flag 包装在 getter/setter 中是否会使它的 "atomicity"无效?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:10:48 27 4
gpt4 key购买 nike

假设我有一个包含 std::atomic_flag 作为私有(private)成员的类,通过 getter 公开。类似于以下内容(伪代码):

class Thing
{
private:

std::atomic_flag ready = ATOMIC_FLAG_INIT;

public:

isReady()
{
return ready.test_and_set();
}
}

我天真的问题是:通过方法查询标志是否会将其变成非原子操作,成为非原子函数调用(或者是?)?我是否应该让我的 ready 标记为公共(public)成员并直接查询它?

最佳答案

不,它没有。 test_and_set() 操作本身是原子的,因此不同线程的调用堆栈有多深并不重要。

为了证明这一点,考虑直接“暴露”atomic_flag 对象的基本情况:

static atomic_flag flag = ATOMIC_FLAG_INIT;

void threadMethod() {

bool wasFirst = !flag.test_and_set();
if( wasFirst ) cout << "I am thread " << this_thread::get_id() << ", I was first!" << endl;
else cout << "I am thread " << this_thread::get_id() << ", I'm the runner-up" << endl;
}

如果两个线程进入threadMethod - 其中一个线程 (t1) 稍早于另一个线程 (t2) 那么我们可以期待控制台输出如下(按相同顺序):

I am thread t1, I was first!
I am thread t2, I'm the runner-up

现在如果两个线程同时进入,但是 t2t1 提前一微秒,但是 t2 然后变得比 t1 慢 当它写入 stdout 时,输出将是:

I am thread t1, I'm the runner-up
I am thread t2, I was first!

...所以对 test_and_set 的调用仍然是原子的,即使输出不一定是预期的顺序。

现在,如果您要将 flag 包装在另一个方法中(不是内联的,只是为了确定),就像这样......

__declspec(noinline)
bool wrap() {
return !flag.test_and_set();
}

void threadMethod() {

bool wasFirst = wrap();
if( wasFirst ) cout << "I am thread " << this_thread::get_id() << ", I was first!" << endl;
else cout << "I am thread " << this_thread::get_id() << ", I'm the runner-up" << endl;
}

...那么程序的行为不会有任何不同 - 因为 falsetruetest_and_set( ) 仍将在每个线程的堆栈中。因此,包装一个 atomic_flag 不会改变它的原子性。

关于c++ - 将 std::atomic_flag 包装在 getter/setter 中是否会使它的 "atomicity"无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44278793/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com