【问题标题】:Atomic Variables Accessed Multiple Times From One Function从一个函数多次访问的原子变量
【发布时间】:2016-05-24 19:35:37
【问题描述】:

我有以下代码:

标题:

class Counter
{
public:
    Conuter(const std::string& fileName);
    boost::uint16_t getCounter();
private:
    tbb::atomic<boost::uint32_t> counter;
    std::string counterFileName;
};

cpp:

Counter::Counter(const std::string& fileName) : counter(), counterFileName(fileName)
{  
    std::string line;
    std::ifstream counterFile (fileName.c_str());  
    if (counterFile.is_open())
    {
        getline (counterFile, line);
        counterFile.close();
    }

    boost::uint32_t temp = std::stoul (line,nullptr,0);
    counter = temp;
}

boost::uint32_t Counter::getCounter()
{
    if (counter > 1000)
    {
        counter = 0;
    }

    assert( counter < 1000);

    const boost::uint32_t ret = counter++;

    if ((counter % 10) == 0)
    {
        // write the counter back to the file.
        std::ofstream file (counterFileName.c_str());
        if (file.is_open())
        {
            myfile << counter;
            myfile.close();
        }
    }
    return ret;
}

在其他地方假设我们有两个线程:

boost::thread t1(&Counter::getCounter, counter);
boost::thread t2(&Counter::getCounter, counter);

我的问题是关于原子变量。由于 getCounter 函数每次调用最多可以访问计数器值 3 次,因此原子变量可以从一次调用更改为下一次调用。例如,如果对 if (counter > 1000) 的调用未能通过,是否有任何保证断言也会通过?也许更具体地说,原子变量会阻塞到函数调用结束吗?或者只要正在读取/写入值?我的第二个问题是,操作系统如何处理原子?就像原子在完成之前不会导致函数阻塞一样,如果一个线程正在更新变量并且一个线程试图将其写出会发生什么?抱歉,这是我第一次尝试无锁数据结构。

【问题讨论】:

  • 变量不会“阻塞”。函数调用块。原子变量的全部意义在于希望访问它们不会阻塞。

标签: c++ multithreading boost tbb


【解决方案1】:

首先,即使在单线程应用程序中,

if (counter > 1000) ...
assert(counter < 1000)

当计数器为 1000 时将失败。

第二,是的,原子变量可以在读取之间轻松更改。它的全部意义在于单次读取是原子的,如果另一个线程在读取变量时准确地更新变量,则可以保证进行正确的内存排序读取(您还可以对算术进行一些保证-您的增量保证增加)。但它没有说明下一次阅读!

如果您需要锁定变量,则需要使用锁定机制,例如互斥锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 2018-07-31
    • 1970-01-01
    • 2022-06-15
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多