文章目录
(一) 线程概念、创建及传参
(二) 独占互斥锁–mutex,lock_guardy与其他mutex
(三) unique_lock替换lock_guardy
(四) 单例模式(Singleton)下的线程安全问题
(五) window临界区
(六) condition_variable条件变量
(七) std::async异步任务与std::future< >
(八) packaged_task< >与promise< >
(九) 原子操作atomic<>简介
(1)简介
- 通俗的说法就是线程根据条件去拿锁,若不符合条件就休眠
- 直到有线程唤醒他,才会继续去竞争锁
- 若线程没有进入休眠状态则另一个线程唤醒无效
(2)使用方法
1.std::condition_variable条件变量的wait()函数可堵塞线程
2.调用wait()第一参数是std::unique_lock,第二参数是函数,返回true则返回,否则线程休眠堵塞
3.调用notify_one()唤醒一个线程,若线程没有进入休眠状态则无效
4.notify_all()由于本程序只有一个互斥量 所有效果与one一样
5.若wait中的线程满足了条件则不断进入竞争锁状态,获得锁则继续执行
6. 第二参数传入lambda表达式用于防止虚假唤醒,如多个线程被同时被唤醒后取数据为空
7. 存在问题:被唤醒后若唤醒线程又进入竞争锁状态可能抢不过
8. 竞争锁有可能存在write的数据堆积,写得不好可能稳定
- wait() 和 notify()配合使用
void wait<_Predicate>(std::unique_lock<std::mutex> &__lock, _Predicate __p)
void wait(std::unique_lock<std::mutex> &__lock)
- wait()不传入第二参数,相当于互斥锁,条件判定一直返回false,即每次都需要其他线程notify()唤醒,若所有唤醒线程结束运行,没有线程唤醒他则堵塞卡死
condition_variable m_codition; //条件变量
std::unique_lock<mutex> myulock(m_mutex); //使用前不能lock
m_codition.wait(myulock);
- 另一个线程
m_codition.notify_one(); //唤醒线程
- wait()传入俩参数,第一个为unique_lock,第二参数为lambda表达式或其他函数,返回值必须为布尔值
- 被唤醒后ambda函数若返回ture则进入竞争锁状态,抢不到则继续判断,抢到则继续执行,被唤醒后lambda函数返回false则继续休眠
std::unique_lock<mutex> myulock(m_mutex1); //使用前不能lock
auto lambda = [this]
{
//判断条件
return true;
};
m_codition.wait(myulock, lambda);
//...
//操作共享数据
//...
myulock.unlock();//提前解锁提高效率
- notify_all()即唤醒所有在wait()中的线程,进入竞争锁状态,由于本程序只有一个互斥量 所有效果与one一样
- 测试代码段
#include <iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
class CReadAndWrite
{
public:
CReadAndWrite() {};
void read();
void wirte();
private:
list<int> m_list;
mutex m_mutex1;
mutex m_mutex2;
condition_variable m_codition; //条件变量
};
void CReadAndWrite::wirte()
{
for (int i = 0; i < 100; i++)
{
std::unique_lock<mutex> myulock(m_mutex1);
m_list.push_back(i);
myulock.unlock();
m_codition.notify_one(); //唤醒线程
cout << "write " << i << endl;
}
}
void CReadAndWrite::read()
{
for (int i = 0; i < 100; i++)
{
std::unique_lock<mutex> myulock(m_mutex1); //使用前不能lock
auto lambda = [this]
{
//cout << "空~~~" << endl;
return !m_list.empty();
};
m_codition.wait(myulock, lambda);
int num = m_list.front();
m_list.pop_front();
myulock.unlock();//提前解锁提高效率
cout << "输出 num = " << num << endl;
}
}
int main()
{
CReadAndWrite obj;
thread mywrite(&CReadAndWrite::wirte, &obj);
thread myread(&CReadAndWrite::read, &obj);
mywrite.join();
myread.join();
std::cout << "Main end!\n";
}