0

我有两个问题 - 考虑两个线程,一个对共享数据进行更改,另一个对共享数据进行操作。两个线程在对数据进行任何操作之前都会获取一个互斥锁。

如何保证对数据进行操作的线程总是看到第一个线程所做的更改?是否需要一组获取/释放栅栏,或者线程是否通过使用互斥锁隐式同步?如果我不使用互斥锁(但要确保独占访问)怎么办?

并且:在没有交错/后续原子操作的情况下,栅栏实际上会做任何事情吗(例如,将标志存储在 atomic_bool 中,发出“准备就绪”或其他信号)?

这是一个用例:

void func()
{
    std::atomic_bool quit = false;

    std::vector<float> data(100);
    std::mutex m;

    std::thread one([&]() 
        {
            while (!quit.load(std::memory_order_relaxed))
            {
                std::unique_lock<std::mutex> lock(m, std::try_to_lock);

                if (lock.owns_lock())
                {
                    for (int i = 0; i < data.size(); ++i)
                    {
                        data[i] = std::rand();
                    }

                    std::atomic_thread_fence(std::memory_order::memory_order_release);
                }
            }
        }
    );

    std::thread two([&]() 
        {
            while (!quit.load(std::memory_order_relaxed))
            {
                std::unique_lock<std::mutex> lock(m, std::try_to_lock);

                if (lock.owns_lock())
                {
                    // guaranteed that any changes from thread one to 'data' is seen after this fence?
                    std::atomic_thread_fence(std::memory_order::memory_order_acquire);

                    auto res = std::accumulate(data.begin(), data.end(), 0);
                    std::cout << "Accumulated result is: " << res << std::endl;
                }
            }
        }
    );

    fgetc(stdin);

    quit.store(true);
    one.join();  two.join();
}
4

2 回答 2

1

如何保证对数据进行操作的线程总是看到第一个线程所做的更改?是否需要一组获取/释放栅栏,或者线程是否通过使用互斥锁隐式同步?

互斥锁做所有的工作。不需要额外的内存栅栏。

如果我不使用互斥锁(但要确保独占访问)怎么办?

这取决于确保exclusive access. 大多数机制不需要使用额外的围栏。[严格来说,独占访问的定义意味着相应的内存排序。]

当访问实际上是并发的时可能需要内存栅栏,但是当访问其他变量时,您希望确保观察到一些不变量。

如果没有交错/后续原子操作(例如,将标志存储在 atomic_bool 中,发出“准备就绪”或其他信号),栅栏实际上会做任何事情吗?

栅栏不仅限于原子操作。实际上栅栏只是屏障,它将所有访问(存储、加载或两者,取决于栅栏的类型)分成两组:栅栏之前和之后。

于 2015-11-16T13:10:01.987 回答
0

Fence 只是硬件使内部缓存与主存储器同步的信号。实际上,它们是执行障碍——并且在通过此障碍之前需要内存同步。由此得名。

于 2015-11-16T16:02:52.293 回答