1. 线程库
C++11封装了操作系统的线程接口函数,这样代码就兼容了不同的操作系统。
#include <thread>
线程的创建
thread
:线程类,实现的成员函数有:
- 构造函数:若想线程执行的内容影响到外部的变量,可以使用指针;或使用std::ref 具体可看下面代码。
- join : 等待线程退出后回收资源。
t1.join();
- joinable: 判断线程是否还在运行
- detach : 线程分离,线程结束后自动释放资源,此时主线程无法再获取子线程的资源了。
std::thread (func,func_parameters).detach();
注意:thread没有拷贝构造。=delete
this_thread
: 命名空间,实现了线程相关的一些函数
- get_id : 获取线程id ->
std::thread::id main_thread_id = std::this_thread::get_id();
- sleep_for : 线程执行时阻塞等待时间片结束。
std::this_thread::sleep_for (std::chrono::seconds(1));
#include <iostream>
#include <thread>
int i = 0;
void func(int& a)
{
std::cout << "child thread:int fun" << std::endl;
a += 11;
}
int main()
{
std::thread t; //创建一个线程对象,但是不执行;一般作为声明。
//构造匿名对象,对t移动赋值
t = std::thread([&] { //构造匿名对象移动赋值给t
std::cout << "i am thread:" << std::this_thread::get_id();
for (int j = 0; j < 10; j++)
i++;
});
//创建线程的同时执行特定的函数,传入可变参数列表;
//因为可变参数列表是右值引用,所以无法传入左值,需要std::ref(i)转换;也可以传地址(用指针)
std::thread t1(func, std::ref(i));
t.join();
t1.join();
//t1.detach();
std::cout << " i:" << i << std::endl;
return 0;
}
2. 线程互斥
#include <mutex>
mutex
:锁类,申请一个锁:std::mutex mtx;
实现的成员函数有:
- lock:加锁->
mtx.lock();
- unlock:解锁->
mtx.unlock();
模板函数——推荐使用这个
- lock_guard:
std::lock_guard<std::mutex> lck (mtx);
构造函数加锁;出了作用域(运作正常退出、抛异常)调用析构函数自动解锁。- unique_lock:
std::unique_lock<std::mutex> lck (mtx);
在lock_guard的基础上,又增加其他的函数。
#include <atomic>
对于
std::atomic<int> x(0);
声明的变量进行操作是原子的,只有完成和没有完成两种状态,不存在被另一个线程中断的情况。
一段代码:
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> x(0);
void func()
{
for (int j = 0; j < 10; j++)
{
x++;
std::cout << std::this_thread::get_id() << "->" << x << " " << std::endl;
}
}
int main()
{
std::thread t1(func);
std::thread t2(func);
t1.join();
t2.join();
return 0;
}
3. 线程同步
#include <condition_variable>
condition_variable : 条件变量类
std::condition_variable cv;
- wait :等待直到线程被唤醒
cv.wait(lck,available);
若available为false,则该线程阻塞等待,相当于while (!available) wait(lck);
- notify_one:唤醒一个线程
- notify_all: 唤醒所有线程
condition_variable : 条件变量类
std::condition_variable cv;
- wait :等待直到线程被唤醒
cv.wait(lck,shipment_available);
三个线程依次打印:
#include <iostream>
#include <thread>
#include <condition_variable>
int main()
{
std::mutex Lock;
std::condition_variable cv;
int num = 0;
//std::atomic<int> available(0);
int available = 0;
std::thread t1([&] {
for (int i = 0; i < 10; i++)
{
std::unique_lock<std::mutex> mut(Lock);
cv.wait(mut, [&available] {
if (available == 0)
return true;
else
return false;
});
num++;
std::cout << std::this_thread::get_id() << "->" << num << std::endl;
available++;
available = available % 3;
//cv.notify_one(); //有概率阻塞
cv.notify_all(); //改成这个后正常运行
}
});
std::thread t2([&] {
for (int i = 0; i < 10; i++)
{
std::unique_lock<std::mutex> mut(Lock);
cv.wait(mut, [&available] {
if (available == 1)
return true;
else
return false;
});
num++;
std::cout << std::this_thread::get_id() << "->" << num << std::endl;
available++;
available = available % 3;
//cv.notify_one();
cv.notify_all();
}
});
std::thread t3([&] {
for (int i = 0; i < 10; i++)
{
std::unique_lock<std::mutex> mut(Lock);
cv.wait(mut, [&available] {
if (available == 2)
return true;
else
return false;
});
num++;
std::cout << std::this_thread::get_id() << "->" << num << std::endl;
available++;
available = available % 3;
//cv.notify_one();
cv.notify_all();
}
});
t1.join();
t2.join();
t3.join();
return 0;
}