【发布时间】: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<SpinLock>& __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