https://paul.pub/cpp-concurrency/
https://zhuanlan.zhihu.com/p/71900518
一次调用
API | 标准 | 说明 |
call_once | c++11 | 在多线程环境下,也能保证某个函数只调用一次 |
once_flag | c++11 | 与call_once配合使用 |
1.1 调用示例
#include <iostream>
#include <thread>
#include <Windows.h>
#include <mutex>
void Init()
{
std::cout << "进行线程工作" << std::endl;
}
void Worker(std::once_flag* flag)
{
std::call_once(*flag, Init);
}
int main()
{
std::once_flag flag;
std::thread th1(Worker,&flag);
std::thread th2(Worker, &flag);
th1.join();
th2.join();
return 0;
}
结果显示两个线程里面只有一个成功执行了init函数
1.2 实现线程安全的单例模式
1.2.1 h文件
#pragma once
#include <iostream>
#include <thread>
#include <Windows.h>
#include <mutex>
class COnceThread
{
public:
static COnceThread* GetInstance();
static void CInit();
private:
static COnceThread* cThread;
COnceThread();
};
1.2.2 cpp文件
#include "COnceThread.h"
COnceThread* COnceThread::cThread = nullptr;
COnceThread::COnceThread()
{
std::cout << "执行了构造函数" << std::endl;
}
void COnceThread::CInit()
{
cThread = new COnceThread();
}
COnceThread* COnceThread::GetInstance()
{
static std::once_flag flag; //static 不能缺少
//std::call_once(flag, &COnceThread::CInit); //第一种方式
std::call_once(flag, [&]() { //第二种方式
cThread = new COnceThread();
});
return cThread;
}
1.2.3 main文件
#include <iostream>
#include "COnceThread.h"
void DoThing()
{
std::cout << "执行线程" << std::endl;
COnceThread* woker = COnceThread::GetInstance();
}
int main()
{
std::thread th1(DoThing);
std::thread th2(DoThing);
th1.join();
th2.join();
return 0;
}
2.线程同步:
当多个线程要访问同一个资源时,可能产生读写冲突,导致数据混乱,进而引起程序崩溃
使用std::mutex进行上锁、解锁操作,预防读写冲突,需要包含mutex头文件
#include <iostream>
#include <vector>
#include <string>
#include <Windows.h>
#include <thread>
#include <mutex>
class Box
{
};
std::mutex mutex1;
std::vector<Box*> p;
void InitBox() //初始化箱子
{
for (int i = 0; i < 9; i++)
{
p.push_back(new Box());
}
std::cout << "初始有" << p.size() << "个箱子" << std::endl;
}
void MoveBox(std::string name) //搬走箱子
{
mutex1.lock();
if (!p.empty())
{
std::cout << name << "搬走了第" << p.size() << "个箱子" << std::endl;
p.pop_back();
Sleep(3000);
}
else
return;
mutex1.unlock();
}
//线程函数
void Fun1()
{
while (1)
{
MoveBox("线程1");
Sleep(5000);
}
}
void Fun2()
{
while (1)
{
MoveBox("线程2");
Sleep(5000);
}
}
int main()
{
std::cout << "主线程启动" << std::endl;
InitBox();
std::thread th1(Fun1);
std::thread th2(Fun2);
th1.join();
th2.join();
return 0;
}