代码之家  ›  专栏  ›  技术社区  ›  Ben

执行变量(C++)的并发修改

  •  0
  • Ben  · 技术社区  · 7 年前

    我正在尝试对一个原子库进行单元测试(我知道原子库不适合进行单元测试,但我仍然想尝试一下)

    为此,我想让x个并行线程增加一个计数器并计算结果值(它应该是x)。

    代码如下。问题是它永远不会坏。这个 Counter 总是很好地结束了2000年(见下文)。我还注意到 cout 也作为一个整体打印(而不是混合,我记得看到的与其他多线程 couts )

    我的问题是:为什么不休息?或者我怎样才能让这段时间过去?

    #include <iostream>
    #include <thread>
    #include <vector>
    #include <mutex>
    #include <condition_variable>
    
    std::mutex m;
    std::condition_variable cv;
    bool start = false;
    
    int Counter = 0;
    
    void Inc() {
    
        // Wait until test says start
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, [] {return start; });
    
        std::cout << "Incrementing in thread " << std::this_thread::get_id() << std::endl;
        Counter++;
    }
    
    int main()
    {
        std::vector<std::thread> threads;
    
        for (int i = 0; i < 2000; ++i) {
            threads.push_back(std::thread(Inc));
        }
    
        // signal the threads to start
        {
            std::lock_guard<std::mutex> lk(m);
            start = true;
        }
        cv.notify_all();
    
        for (auto& thread : threads) {
            thread.join();
        }
    
        // Now check whether value is right
        std::cout << "Counter: " << Counter << std::endl;
    }
    

    结果是这样的(然后是2000行)

    Incrementing in thread 130960
    Incrementing in thread 130948
    Incrementing in thread 130944
    Incrementing in thread 130932
    Incrementing in thread 130928
    Incrementing in thread 130916
    Incrementing in thread 130912
    Incrementing in thread 130900
    Incrementing in thread 130896
    Counter: 2000
    

    任何帮助都将不胜感激

    更新:将线程数目减少到4,但在for循环中(如@tkausl建议的那样)增加了100万次 咳嗽 的线程ID似乎是连续的。

    update2:结果是锁必须被解锁,以防止对每个线程的独占访问( lk.unlock() )额外的 yield 在for循环中增加了竞争条件的影响。

    1 回复  |  直到 7 年前
        1
  •  3
  •   felix    7 年前

    cv.wait(lk, [] {return start; }); 只返回 lk 获得。所以它是独家的。你可能想解锁 LK 刚好在…之后:

    void Inc() {
        // Wait until test says start
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, [] {return start; });
        lk.unlock();
    
        Counter++;
    }
    

    你必须移除 std::cout ,因为它可能会引入同步。

    推荐文章