【问题标题】:Inconsistencies in the output while reading and writing simultaneously同时读取和写入时输出不一致
【发布时间】:2017-06-09 11:34:29
【问题描述】:

为什么这段代码会产生不一致的读取器函数输出?

#include <cstdio>
#include <thread>
#include <mutex>

std::mutex mu;
int i = 0;

void writeThread()
{
    for (int j = 0; j < 1000; ++j)
    {
        std::lock_guard<std::mutex> lock(mu);
        printf ("write i: %d\n", ++i);
    }
}

void readThread()
{
    for (int j = 0; j < 1000; ++j)
        printf ("Read i = %d\n", i);
}

int main()
{
    std::thread t(writeThread);
    std::thread z(readThread);
    t.join();
    z.join();
    return 0;
}

我有时会得到类似的东西:

write i: 996
write i: 997
Read i = 980 <--- wrong reader output starting here
Read i = 998
Read i = 998
write i: 998
Read i = 998
write i: 999
Read i = 999

只是输出错误还是我真的需要在阅读器函数中使用互斥锁?

【问题讨论】:

  • 输出有什么问题?如果与作者没有同步,你为什么认为读者应该看到任何特定的价值? (严格来说,这是一个具有完全未定义行为的数据竞赛)。
  • 顺便说一下,对于这个例子,你可以使用原子类型,即std::atomic_int i = 0 - 根本不需要互斥体,并且没有数据竞争,尽管你可能仍然看不到你想要的输出.
  • 这个特殊的例子非常简单。我正在开发的程序读取和写入 STL 和一些更复杂的数据结构。
  • 代码存在数据竞争。它的行为是不确定的。

标签: c++ multithreading synchronization


【解决方案1】:

只是输出错误还是我真的需要在阅读器函数中使用互斥锁?

输出没有错,如果您有两个或多个线程访问一个变量并且其中至少一个是写入器,那么您需要提供同步。由于readThread 不等待WriteThread 写信给i,所以你有一个竞争条件。这是未定义的行为,您得到的任何输出都是“正确的”。要解决此问题,您需要将 std::lock_guard&lt;std::mutex&gt; lock(mu); 添加到 readThread 喜欢

void readThread()
{
    for (int j = 0; j < 1000; ++j)
    {
        std::lock_guard<std::mutex> lock(mu);
        printf ("Read i = %d\n", i);
    }
}

如果您有更多的读者,那么您就有了作者,您可以使用std::shared_mutex,这将允许多个读者同时阅读,但当其中一个作者需要写入时,将阻止所有读者和其他作者。

【讨论】:

  • 我明白了。因此,如果我有 500 个读取器线程,并且每个读取器线程在读取时都阻塞互斥锁,那不就和只有一个线程一样慢吗?
  • @ScepticalJule 刚刚添加到关于这个的答案中。
猜你喜欢
  • 1970-01-01
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多