【问题标题】:Condition variable custom wait function条件变量自定义等待函数
【发布时间】:2021-08-23 22:34:54
【问题描述】:

我创建了自定义 SpinLock 类

我想在条件变量中使用这个类,但是有一个错误

error: no matching function for call to ‘std::condition_variable::wait(std::unique_lock<Spinlock>&)’
                 cv_.wait(lk);

cv_.wait(lk); 行有错误

如何为条件变量支持我的 SpinLock?

我想声明自己的函数等待void wait(unique_lock&lt;SpinLock&gt;&amp; __lock, _Predicate __p)签名。

#include <atomic>
#include <iostream>
#include <string>
#include <cstdlib> // atoi
#include <thread> // thread
#include <mutex> // mutex
#include <condition_variable>
#include <vector>

using namespace std;


class Spinlock {
private:
    std::atomic_flag lock_ = ATOMIC_FLAG_INIT;
public:
    void lock()
    {
        while (lock_.test_and_set(std::memory_order_acquire)) continue;
    }
    void unlock()
    {
        lock_.clear(std::memory_order_release);
    }
};


class PrintOrder final {
public:
    PrintOrder(int n, int threadNum)
        : maxNum_(n)
        , curNum_(0)
    {
        startTime_ = chrono::steady_clock::now();
        
        threads_.reserve(threadNum);
        unique_lock<Spinlock> lk(spinLock_);
        for(int x = 0; x < threadNum; ++x)
        {
            threads_.emplace_back(&PrintOrder::background, this, x);
        }
    }

    ~PrintOrder() {
        for(auto&& th : threads_)
        {
            th.join();
        }

        auto endTime = chrono::steady_clock::now();
        auto diff = endTime - startTime_;
        cout << chrono::duration <double, milli> (diff).count() << " ms" << endl;
    }

    void background(int x) {
        while(true) {
            unique_lock<Spinlock> lk(spinLock_);
            // wait until it's this thread's turn or curNum_ > maxNum_
            while((curNum_ % threads_.size()) != x and curNum_ <= maxNum_)
            {
                cv_.wait(lk);
            }
            if(curNum_ > maxNum_)
            {
                break;
            }

            cout << curNum_ << endl;
            ++curNum_;
            cv_.notify_all();
        }
    }

private:
    int maxNum_;
    int curNum_;
    Spinlock spinLock_;
    condition_variable cv_;
    vector<thread> threads_;

    chrono::time_point<chrono::steady_clock> startTime_;
};

int main(int argc, char **argv) {
    if (argc == 3)
    {
        int maxNum = atoi(argv[1]);
        int threadsNum = atoi(argv[2]);
        PrintOrder printOrder(maxNum, threadsNum);
    } else {
        cout << "ERROR: expected console input: <maxNum> <threadsNum>" << endl;
    }
    return 0;
}

【问题讨论】:

  • 在这里使用std::condition_variable_any 不适合吗?还是我误解了这个问题?
  • 您的自旋锁非常耗电。考虑添加一条指令来通知 OS/CPU 您处于自旋等待循环中。 (例如,在 x86/x64 上可用的 _mm_pause() 内在函数。)没有它,循环将使用完整的 CPU 线程,这可以提高当前 CPU 频率或减慢其他线程。
  • @G.M.我必须支持线程的顺序。
  • @1201ProgramAlarm 你能举个例子吗?

标签: c++ multithreading condition-variable spinlock


【解决方案1】:

std::condition_variable 仅支持std::unique_lock&lt;std::mutex&gt;。请改用std::condition_variable_any

condition_variable_any 类是std::condition_variable 的泛化。而std::condition_variable 仅适用于std::unique_lock&lt;std::mutex&gt;condition_variable_any 可以操作任何满足BasicLockable 要求的锁。

【讨论】:

  • 谢谢! condition_variable_any 帮助我)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 2015-07-01
  • 1970-01-01
  • 2020-05-20
相关资源
最近更新 更多