参考引用
- C++11 14 17 20 多线程从原理到线程池实战
- 代码运行环境:Visual Studio 2019
thread_RAII.cpp
#include
#include
#include
#include
using namespace std;
// RAII
class XMutex {
public:
// 在构造函数中锁住,一生成对象 mux 就拿到锁
XMutex(mutex &mux) : mux_(mux) {
cout << "Lock" << endl;
mux.lock();
}
// 析构函数中释放
~XMutex() {
cout << "Unlock" << endl;
mux_.unlock();
}
private:
// 引用方式存储锁,引用必须在初始化时就要赋值
mutex& mux_;
};
static mutex mux;
void TextMutex(int status) {
XMutex lock(mux); // 不需要关心锁的 unlock() 释放
if (status == 1) {
cout << " = 1" << endl;
return;
} else {
cout << " != 1" << endl;
return;
}
} // 超出这个大括号后,会调用析构函数释放栈中资源
int main(int argc, char* argv[]) {
TextMutex(1);
TextMutex(2);
getchar();
return 0;
}
控制台输出
Lock
= 1
Unlock
Lock
!= 1
Unlock
C++11 实现严格基于作用域的互斥体所有权包装器
adopt_lock:C++11 类型为 adopt_lock_t,假设调用方已拥有互斥的所有权
通过 {} 控制锁的临界区(栈区间),出了 {} 后自动释放锁资源
thread_RAII2.cpp
#include
#include
#include
#include
using namespace std;
static mutex gmutex;
void TestLockGuard(int i) {
gmutex.lock();
{
// 已经拥有锁,不锁定,退出解锁
lock_guard<mutex> lock(gmutex, adopt_lock);
// 结束释放锁
}
{
lock_guard<mutex> lock(gmutex);
cout << "begin thread " << i << endl;
}
for (;;) {
{
lock_guard<mutex> lock(gmutex);
cout << "In " << i << endl;
}
this_thread::sleep_for(500ms);
}
}
int main(int argc, char* argv[]) {
for (int i = 0; i < 3; i++) {
thread th(TestLockGuard, i + 1);
th.detach();
}
getchar();
return 0;
}
控制台输出
begin thread 1
In 1
begin thread 3
In 3
begin thread 2
In 2
In 1
In 2
In 3
In 1
...
支持临时释放锁 unlock
支持 adopt_lock:(已经拥有锁,不加锁,出栈区会释放)
支持 defer_lock:(延后拥有,不加锁,出栈区不释放)
支持 try_to_lock:尝试获得互斥的所有权而不阻塞,获取失败退出栈区不会释放,通过 owns_lock() 函数判断
thread_RAII3.cpp
#include
#include
#include
#include
using namespace std;
int main(int argc, char* argv[]) {
{
static mutex mux;
{
unique_lock<mutex> lock(mux);
lock.unlock(); // 临时释放锁
lock.lock();
}
{
// 已经拥有锁 不锁定,退出栈区解锁
mux.lock();
unique_lock<mutex> lock(mux, adopt_lock);
}
{
// 延后加锁 不拥有 退出栈区不解锁
unique_lock<mutex> lock(mux, defer_lock);
// 加锁 退出栈区解锁
lock.lock();
}
{
//mux.lock();
// 尝试加锁 不阻塞 失败不拥有锁
unique_lock<mutex> lock(mux, try_to_lock);
if (lock.owns_lock()) {
cout << "owns_lock" << endl;
} else {
cout << "not owns_lock" << endl;
}
}
}
getchar();
return 0;
}
int main(int argc, char* argv[]) {
{
// 共享锁
static shared_timed_mutex tmux;
// 读取锁--共享锁
{
// 调用共享锁
shared_lock<shared_timed_mutex> lock(tmux);
cout << "read data" << endl;
// 退出栈区 释放共享锁
}
// 写入锁--互斥锁
{
unique_lock<shared_timed_mutex> lock(tmux);
cout << "write data" << endl;
}
}
}
#pragma once
#include
class XThread {
public:
// 启动线程
virtual void Start();
// 设置线程退出标志 并等待
virtual void Stop();
// 等待线程退出(阻塞)
virtual void Wait();
// 线程是否退出
bool is_exit();
private:
// 线程入口
virtual void Main() = 0;
bool is_exit_ = false;
std::thread th_;
};
#include "xthread.h"
using namespace std;
// 启动线程
void XThread::Start() {
is_exit_ = false;
th_ = thread(&XThread::Main, this);
}
// 设置线程退出标志 并等待
void XThread::Stop() {
is_exit_ = true;
Wait();
}
// 等待线程退出(阻塞)
void XThread::Wait() {
if (th_.joinable())
th_.join();
}
// 线程是否退出
bool XThread::is_exit() {
return is_exit_;
}
#pragma once
#include "xthread.h"
#include
#include
#include
class XMsgServer : public XThread {
public:
// 给当前线程发消息
void SendMsg(std::string msg);
private:
// 处理消息的线程入口函数
void Main() override;
// 消息队列缓冲
std::list<std::string> msgs_;
// 互斥访问消息队列
std::mutex mux_;
};
#include "xmsg_server.h"
#include
using namespace std;
using namespace this_thread;
// 处理消息的线程入口函数
void XMsgServer::Main() {
while (!is_exit()) {
sleep_for(10ms);
unique_lock<mutex> lock(mux_);
if (msgs_.empty())
continue;
while (!msgs_.empty()) {
// 消息处理业务逻辑
cout << "recv : " << msgs_.front() << endl;
msgs_.pop_front();
}
}
}
// 给当前线程发消息
void XMsgServer::SendMsg(std::string msg) {
unique_lock<mutex> lock(mux_);
msgs_.push_back(msg);
}
#include "xmsg_server.h"
#include
using namespace std;
int main(int argc, char* argv[]) {
XMsgServer server;
server.Start();
for (int i = 0; i < 10; i++) {
stringstream ss;
ss << " msg : " << i + 1;
server.SendMsg(ss.str());
this_thread::sleep_for(500ms);
}
server.Stop();
return 0;
}
std::condition_variable cv;
unique_lock lock(mux);
msgs_.push_back(data);
lock.unlock();
cv.notify_one(); // 通知一个等待信号线程
cv.notify_all(); // 通知所有等待信号线程
unique_lock lock(mux);
// 解锁,并阻塞等待 notify_one notify_all 通知
cv.wait(lock);
// 接收到通知会再次获取锁标志,也就是说如果此时 mux 资源被占用,wait 函数会阻塞
msgs_.front();
// 处理数据
msgs_pop_front();
#include
#include
#include
#include
#include
#include
using namespace std;
list<string> msgs_;
mutex mux;
condition_variable cv;
void ThreadWrite() {
for (int i = 0;;i++) {
stringstream ss;
ss << "Write msg " << i;
unique_lock<mutex> lock(mux);
msgs_.push_back(ss.str());
lock.unlock();
cv.notify_one(); // 发送信号
//cv.notify_all();
this_thread::sleep_for(3s);
}
}
void ThreadRead(int i) {
for (;;) {
cout << "read msg" << endl;
unique_lock<mutex> lock(mux);
//cv.wait(lock); // 解锁、阻塞等待信号
cv.wait(lock, [i]
{
cout << i << " wait" << endl;
return !msgs_.empty();
});
// 获取信号后锁定
while (!msgs_.empty()) {
cout << i << " read " << msgs_.front() << endl;
msgs_.pop_front();
}
}
}
int main(int argc, char* argv[]) {
thread th(ThreadWrite);
th.detach();
for (int i = 0; i < 3; i++) {
thread th(ThreadRead, i + 1);
th.detach();
}
getchar();
return 0;
}