浏览有关小城镇建设的网站,wordpress作者墙主题,如何装wordpress,如何利用谷歌云做自己的网站C 多线程#xff08;一#xff09;1.std中的thread API 介绍开启一个线程获取线程信息API交换两个线程2.向线程里传递参数的方法第一种方式#xff08;在创建线程的构造函数后携带参数#xff09;第二种方式#xff08;Lambda#xff09;第三种方式#xff08;成员函数 多线程一1.std中的thread API 介绍开启一个线程获取线程信息API交换两个线程2.向线程里传递参数的方法第一种方式在创建线程的构造函数后携带参数第二种方式Lambda第三种方式成员函数3.互斥锁4.try_lock5.挂起和唤醒线程6.将主线程资源移动到其他线程7.lock_guard8.unique_lock9.call_once10.condition_variable1.std中的thread API 介绍
开启一个线程
如下是定义一个线程
std::thread Thread1(ThreadFunc1)其开始运行有两种方式一个是阻塞当前调用进程一个是异步的方式不会阻塞当前调用的进程
join会阻塞当前调用的进程
Thread1.join()detach不会阻塞当前调用进程
Thread1.detach()获取线程信息API
获取线程ID
Thread1.get_id()判断线程是否是可启用的
Thread1.joinable() 这样输出的值是true std::thread Thread1(ThreadFunc1);cout Thread1.joinable() endl;如果传入的执行参数为空则是不可启用 std::thread Thread1;cout Thread1.joinable() endl;如果想获取计算机能创建的线程数
Thread1.hardware_concurrency()获取当前线程ID std::this_thread::get_id()使当前线程睡眠n秒 有两种方式一种是std的一种是windows底层的 std::this_thread::sleep_for(chrono::seconds(2));注意windows的睡眠需要引用头文件Windows.h
#include Windows.h
Sleep(1000);交换两个线程
std::thread Thread1(ThreadFunc1)
std::thread Thread2(ThreadFunc2)
Thread1.spawn(Thread2)2.向线程里传递参数的方法
先定义要在子线程执行的方法
void Func1(int a, const string b)
{cout a endl;cout b endl;
}第一种方式在创建线程的构造函数后携带参数 std::thread NewThread1(Func1, 1, Hello);NewThread1.join();第二种方式Lambda int a 100;std::thread NewThread2([](int value1,const string value2){cout endl;cout a endl;cout value1 endl;cout value2 endl;},2,World);NewThread2.join();第三种方式成员函数
class FTestClass
{
public:void Run(int a,const string b){cout a endl;cout b endl;}
};FTestClass TestClass;std::thread NewThread3(FTestClass::Run, TestClass, 3, TestClass);NewThread3.join();3.互斥锁
为了避免多线程之间的资源竞争自然需要这种互斥的锁
使用前需要引用头文件
#include mutexmutex mx;
void NewThreadFunc()
{mx.lock();cout 等待2s endl;std::this_thread::sleep_for(chrono::seconds(2));mx.unlock();
}for (size_t i 0; i 5; i){std::thread th(NewThreadFunc5);th.detach();}最后我们会发现每隔2s输出一次信息
我们每次使用锁都需要lock 和 unlock 这是十分不便利的而且如果我们忘记解锁就会死锁 我们可以使用析构来实现这种自动解锁的方式
struct FEvent
{FEvent(){m.lock();}~FEvent(){m.unlock();}static mutex m;
};
mutex FEvent::m;再使用宏包裹一下
#define LOCK_TEST FEvent LockEvent;如下是在线程执行的函数只需要定义一行就可以自动解锁
void NewThreadFunc()
{LOCK_TESTcout 等待2s endl;std::this_thread::sleep_for(chrono::seconds(2));
}4.try_lock
try_lock 返回bool 值是否能上锁
static mutex mx;
void NewThreadFunc2()
{if (mx.try_lock()){cout 等待2s endl;std::this_thread::sleep_for(chrono::seconds(2));mx.unlock();}else {cout 锁被使用 endl;}
}for (size_t i 0; i 5; i){std::thread NewThread2(NewThreadFunc2);NewThread2.detach();}最后输出我们会发现只打印了一个等待2s 和四个锁被使用
5.挂起和唤醒线程
定义在子线程执行的函数
void NewThreadFunc3()
{while (true){Sleep(1000);cout Hello endl;}
}SuspendThread 用于挂起线程 ResumeThread 用于唤醒线程 std::thread th(NewThreadFunc3);SuspendThread(th.native_handle());std::this_thread::sleep_for(chrono::seconds(2));ResumeThread(th.native_handle());6.将主线程资源移动到其他线程
定义在子线程执行的函数
void NewThreadFunc4(const string Value)
{cout Value endl;
}std::thread th1(NewThreadFunc4,move(Hello world));std::thread th2 move(th1);th2.detach();将th1的所有权转移给th2。此时th1不再代表任何线程相当于th1处于“空”状态而th2现在代表原来th1所代表的线程。这是因为std::thread是不可复制的但可以移动。所以这里通过移动赋值或移动构造将th1的线程所有权转移给th2。
7.lock_guard
类似我们之前自己封装的自动解锁的锁不要手动调用unlock函数执行完毕自动析构
mutex mx;
void NewThreadFunc5()
{lock_guardmutex lock(mx);cout Hello world endl;Sleep(2000);
}for (size_t i 0; i 5; i){std::thread th(NewThreadFunc5);th.detach();}每隔2s输出一次一共输出了5次
8.unique_lock
unique_lock 相对于上面的 lock_guard 多了更多的功能API 可以更自由丰富的操作锁
defer_lock 此参数是延时的意思锁并不是立马生效需要手动lock
unique_lock 也是过了作用域会自动解锁
static mutex mt;
void Func1()
{unique_lockmutex lock1(mt,defer_lock);// 不需要上锁的函数cout 这是不需要上锁的函数 endl;lock1.lock();cout 这是需要上锁的函数 endl;lock1.unlock();//lock2.try_lock_until(); 锁到某个时间点//lock2.release(); 释放//lock2.mutex();拿到锁本体//lock2.swap(); 交换//lock2.owns_lock(); 判断是否锁住
}下面演示一个unique_lock 的 try_lock_for()方法
static timed_mutex timeMt;
void Func2()
{unique_locktimed_mutex lock2(timeMt, defer_lock);if (lock2.try_lock_for(chrono::seconds(2))){cout 锁住2s后 endl;this_thread::sleep_for(chrono::seconds(1));}else{cout 锁正在被占用 endl;}
}for (size_t i 0; i 5; i){thread th(Func2);th.detach();}我们会发现输出了2个锁住2s后和3个锁正在被占用是因为这个锁定义了锁住的时间为2s当第一次运行后只执行了1s第二次进入仍然没超过定义的锁的2s所以可以进入而之后都超过2s了故无法进入了。
9.call_once
顾名思义就是无论调用多少次只执行一次
once_flag oneFlag;
void Func3()
{call_once(oneFlag, [](){cout 运行一次 endl;});
}for (size_t i 0; i 5; i){Func3();}10.condition_variable
条件变量一个地方可以等待直到通知这个等待就可以执行等待之后的代码
mutex tx1;
condition_variable cv;
void Func4()
{Sleep(1000);cv.notify_one();Sleep(1000);
}std::thread th(Func4);th.detach();unique_lockmutex Lock1(tx1);cv.wait(Lock1);cout 运行Wait之后 endl;notify_one 是一个还有多个版本notify_all