线程间通信
1.互斥对象
mutex g_lock;
g_lock.lock();
g_lock.unlock();
std::mutex; //非递归的互斥量
std::timed_mutex; //带超时的非递归互斥量
std::recursive_mutex; //递归互斥量
std::recursive_timed_mutex; //带超时的递归互斥量
2.自动锁 lock_gurad
//传入的mutex对象(即它所管理的mutex对象)会被当前线程锁住
//在lock_guard对象被析构时,它所管理的mutex对象会自动解锁
lock_guard loker(g_lock);
std::unique_lock
std::mutex mtx;
std::unique_lockstd::mutex my_lock (mtx, std::defer_lock);
if(my_lock.try_lock())//加锁成功则执行下面的操作
{
}
3.unique_lock
unique_lock g2(mut, try_to_lock);//尝试加锁一次,但如果没有锁定成功,会立即返回,不会阻塞在那里,且不会再次尝试锁操作。
if (g2.owns_lock()) {//锁成功
}
adopt_lock表示构造函数中不再进行互斥量锁定,因此此时需要提前手动锁定。
try_to_lock: 尝试去锁定,得保证锁处于unlock的状态,然后尝试现在能不能获得锁;尝试用mutx的lock()去锁定这个mutex,但如果没有锁定成功,会立即返回,不会阻塞在那里,并继续往下执行;
defer_lock: 始化了一个没有加锁的mutex;
条件锁condition_variable
wait(locker) :wait 函数需要传入一个std::mutex(一般会传入std::unique_lock对象),即上述的locker。wait函数会自动调用 locker.unlock() 释放锁(因为需要释放锁,所以要传入mutex)并阻塞当前线程,本线程释放锁使得其他的线程得以继续竞争锁。一旦当前线程获得notify(通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数此时再自动调用 locker.lock()上锁。
cond.notify_one(): 随机唤醒一个等待的线程
cond.notify_all(): 唤醒所有等待的线程
mutex mtx;
condition_variable cv;
class Deque
{
public:
void Push(int n)
{
unique_lock<mutex>lock(mtx);
/*while (que.size() > 0)
{
cv.wait(lock);
}*/
cv.wait(lock, [this]() {return this->que.size() <= 0; });
que.push_back(n);
cout << "生产:" << n << endl;
cv.notify_all();
}
int Pop()
{
unique_lock<mutex>lock(mtx);
/*while (que.size() <= 0)
{
cv.wait(lock);
}*/
cv.wait(lock, [this]() {return this->que.size() > 0; });
int n = que.front();
que.erase(que.begin());
cout << "消费:" << n << endl;
cv.notify_all();
return n;
}
int Size()
{
lock_guard<mutex>lock(mtx);
return que.size();
}
private:
vector<int>que;
};
void Sell(Deque *que)
{
for (int i = 1; i < 11; i++)
{
int n = que->Pop();
}
}
int main()
{
Deque que;
thread t1(Product,&que);
thread t2(Sell,&que);
t1.join();
t2.join();
}
下面这两个是等价的
/*while (que.size() <= 0)
{
cv.wait(lock);
}*/
cv.wait(lock, [this]() {return this->que.size() > 0; });
wait_for(阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后)
std::condition_variable cv;
std::mutex cv_m;
int i;
void waits(int idx)
{
std::unique_lock<std::mutex> lk(cv_m);
if(cv.wait_for(lk, idx*100ms, []{return i == 1;}))
std::cerr << "Thread " << idx << " finished waiting. i == " << i << '\n';
else
std::cerr << "Thread " << idx << " timed out. i == " << i << '\n';
}