0、thread的成员函数
myjob.join();//阻塞主线程,使得子线程执行完毕之后再执行主线程。 myjob.detach();//解除主线程与子线程的关系,两者独立执行,主线程执行完毕后会自动退出。 joinable();//用于检测线程是否joinable joinable : 代表该线程是可执行线程。 not-joinable :通常一下几种情况会导致线程成为not-joinable 1) 由thread的缺省构造函数构造而成(thread()没有参数)。 2) 该thread被move过(包括move构造和move赋值) 3) 该线程调用过join或者detach detach方式下注意事项: (1)detach()方式时,传指针如果主线程先执行完会发生错误,引用会拷贝不推荐使用。 (2)传递简单数据类型,建议值传递代替引用 (3)传递类对象,避免隐式类型转换,创建线程时使用显示类型转换,并且类对象中函数使用引用。 //std::ref(A)作用:线程传对象时传递参数对象,不进行另外的拷贝 //cout<<"main thread id is : "<<std::this_thread::get_id() << endl;//获取线程id1、互斥量mutex类中有lock() 和unlock()函数、存在多个锁时,加锁顺序一致以防死锁 2、std::lock_guard为类模板,可以取代lock、unlock,可以自己释放锁 //lock_guard构造时调用lock(),析构时调用unlock() 3、std::lock(),锁住两个及两个以上的互斥量。一次加所有锁,要么全加锁要么不加锁。不存在加锁顺序导致死锁的问题 //示例:lock(mutex1,mutex2,…); 4、std::lock_guard()与std::lock()结合使用 //示例: //std::lock(mutex1,mutex2); //std::lock_guard guard(mutex1,std::adopt_lock);//使用adpot_lock参数,其为结构体对象 //std::lock_guard guard(mutex2,std::adopt_lock);//使用adpot_lock参数
5、unique_lock是类模板,比lock_guard()更灵活,效率相对低,内存占用高 5.1 初始化参数 adopt_lock(需要提前lock) adpot_lock参数使得构造时不调用mutex的lock函数 示例:
mutex1.lock(); unique_lock<mutex> guard(mutex1,std::adopt_lock);5.2 初始化参数std::try_to_lock 在构造unique_lock时尝试加锁,加锁失败则返回,不会阻塞。使用时不能提前加锁 5.3 初始化参数std::defer_lock初始化没有加锁的mutex
6、unique_lock 成员函数 6.1 lock() 不用自己unlock() 6.2 unlock() 用户灵活解锁 6.3 bool try_lock() 尝试加非阻塞锁,加锁成功返回true,加锁失败返回false 6.4 release(),返回它所管理的mutex对象指针,并释放其所有权。解除mutex与unique_lock的联系 7、unique_lock的所有权传递,unique_lock的mutex可以转移,不能复制 //两个unique_lock间转移mutex所有权: unique_lock2(std::move(unique_lock1)) // 通过其他函数返回的unique_lock对象初始化 :
std::unique_lock<std::mutex> unique_lock2 = return_lock()//return_lock 返回另一个unique_lock对象8、sleep 一些毫秒
std::chrono::milliseconds dura(2000);//2秒 std::this_thread::sleep_for(dura);//休息2秒9、代码Demo
#include <iostream> #include <thread> #include <vector> #include <queue> #include <mutex> using namespace std; void myprint(const int &i, char* pmybuf) { cout << i << endl; cout << "main thread id is : " << std::this_thread::get_id() << endl; cout << pmybuf << endl; } class A { public: int val; A(int s):val(s) { cout << "构造" << endl; } ~A() { cout << "析构" << endl; } void print(int num) { cout << "print num is :" << num << endl; } }; class B { private: queue<int> que; mutex my_mymutex;//互斥量 private: //删除元素 bool popCore(int &num) { my_mymutex.lock();//加锁 if (!que.empty()) { num = que.front(); que.pop(); my_mymutex.unlock();//解锁 return true; } my_mymutex.unlock();//解锁 return false; } bool popCore2(int &num) { //std::lock_guard<mutex> guard(my_mymutex);//使用lock_guard std::unique_lock<std::mutex> guard(my_mymutex);//使用unique_lock std::chrono::milliseconds dura(2000);//2秒 std::this_thread::sleep_for(dura);//休息2秒 if (!que.empty()) { num = que.front(); que.pop(); return true; } return false; } public: //插入元素 void insert() { for (int i = 0; i < 1000; i++) { cout << "插入元素 i: " << i << endl; std::unique_lock<std::mutex> guard(my_mymutex, std::try_to_lock);//使用unique_lock if (guard.owns_lock()) { cout << "加锁成功" << endl; que.push(i); } else cout << "加锁失败" << endl; } } //删除元素对外接口 void pop() { int num; for (int i = 0; i < 1000; i++) { if (popCore2(num)) cout << "出队 数字 num :"<< num << endl; else cout << "que is NULL" << endl; } } }; int main() { /* int num =10; char[] buf = "this is a buf"; thread myjob(myprint,num,buf);//可调用函数、对象等,myprint为可调用函数,有参数的话后跟其参数 if (myjob.joinable()) cout << "join true1" << endl; else cout << "join false1" << endl; myjob.join();//阻塞主线程,使得子线程执行完毕之后再执行主线程。 */ /* lamada表达式作为线程执行对象 auto mylamdathread = [] { cout << "lamda thread bgein" << endl; cout << "lamda thread end" << endl; }; thread myjob2(mylamdathread); myjob2.join(); cout << "hello" << endl; */ /*类成员函数指针做线程执行对象 A myobj(10); thread myjob4(&A::print,myobj,20); myjob4.join(); */ /*创建多个线程,各子线程之间顺序靠操作系统调度 vector<thread> threads; for (int i = 0; i < 10; i++) threads.push_back(thread(print,i)); for (auto it = threads.begin(); it != threads.end(); ++it) it->join(); */ B b; thread insert_thread(&B::insert, &b); thread pop_thread(&B::pop, &b); insert_thread.join(); pop_thread.join(); cout << "hello" << endl; return 0; }条件变量condition_variable、wait、notify_one、notify_all
#include <iostream> #include <thread> #include <vector> #include <queue> #include <mutex> using namespace std; class B { private: queue<int> que; mutex my_mymutex;//互斥量 std::condition_variable my_cond;//条件变量 public: //插入元素 void insert() { for (int i = 0; i < 1000; i++) { std::unique_lock<std::mutex> guard(my_mymutex);//使用unique_lock cout << "插入元素 i: " << i << endl; que.push(i); my_cond.notify_one();//通知一个线程唤醒wait的线程 //notify_all()通知所有线程唤醒wait的线程,唤醒的多个线程争用锁 } } //删除元素对外接口 void pop() { int num = 0; while (true) { std::unique_lock<std::mutex> guard(my_mymutex); //wait()没有第二个参数或第二个参数返回false则解锁互斥量,阻塞;直到其他线程调用notify_one()函数 my_cond.wait(guard, [this] {//lambda表达式 if (!que.empty()) return true; return false; }); num = que.front(); que.pop(); guard.unlock();//灵活释放锁,可由unique_lock对象析构时释放 cout << "出队元素为:" <<num << endl; } } }; int main() { B b; thread insert_thread(&B::insert, &b); thread pop_thread(&B::pop, &b); insert_thread.join(); pop_thread.join(); cout << "hello" << endl; return 0; }原子操作、std::async()使用
1、std::async为函数模板,返回std::future类对象 作用为创建异步任务
(1)参数std::launch::deferred表示任务等待get()或wait()时执行,延迟调用,不创建线程,主线程中执行 示例:std::future<int> result = std::async(std::launch::deferred,mythread) (2)参数std::launch::async调用async()时创建执行子线程异步执行 (3)std::launch::async | std::launch::deferred,首先创建新线程异步执行,创建失败时则延迟主线程执行2、std::packaged_task 打包任务,类模板 示例:std::packaged_task<int(int)> mypt(mythread);
3、std::promise类模板,在某个线程中给它赋值,其他线程中可以使用
4、std::future result = std::async(mythread,10);
std::future_status status = result.wait_for(std::chrono::seconds(1));//等待1s返回枚举类型 std::future_status: (1)ready ,线程执行完毕 (2)timeout,超时,线程未执行完毕 (3)deferred,async的第一个参数设置为std::launch::deferred,由主线程延迟执行5、可以定义为原子操作的运算符:++、–、+=、-=,&=、|=等
//定义全局变量 std::atomic<int> num;//原子操作对象(1)atomic的load()函数以原子方式读 auto num2 (num.load());
(2)atomic的store()函数以原子方式写 num2.store(123);
#include <iostream> #include <thread> #include <vector> #include <queue> #include <mutex> #include <future> using namespace std; //全局变量 std::atomic<int> num;//原子操作对象 int mythread(int num) { cout << "thread begin, thread id is :" << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(2000);//休息2秒 std::this_thread::sleep_for(dura); cout << "thread end" << endl; return 5; } //promise类模板使用,在某个线程中给它赋值,其他线程中可以使用 void func(std::promise<int> &temp, int calc) { calc++; calc *= 10; std::chrono::milliseconds dura(2000);//休息5秒 std::this_thread::sleep_for(dura); int result = calc; temp.set_value(result); } //原子操作演示 void addNum() { for (int i = 0; i < 1000; i++) num++;//atomic对象的操作是原子操作 } int main() { int num = 3; cout << "main thread id is :" << std::this_thread::get_id() << endl; //1、std::async为函数模板,返回std::future类对象 作用为创建异步任务 std::future<int> result = std::async(mythread,num);//以mythread()为执行对象创建一个后台线程,此时不会阻塞 //std::future<int> result = std::async(mythread);//async(&A::func,&a,参数), //A类的成员函数func做执行对象,a为A的对象,参数为func的参数 //2、(1)参数std::launch::deferred表示任务等待get()或wait()时执行 //延迟调用,不创建线程,主线程中执行 //示例:std::future<int> result = std::async(std::launch::deferred,mythread) //(2)参数std::launch::async调用async()时创建执行子线程 //(3)std::launch::async | std::launch::deferred,首先创建新线程异步执行,创建失败时则延迟主线程执行 cout << result.get() << endl;//阻塞直到result返回结果,get函数只能调用一次 cout << "结束" << endl; /* //3、std::packaged_task 打包任务,类模板 //std::packaged_task<int(int)> mypt(mythread); std::packaged_task<int(int)> mypt([](int num) {//包装lambda表达式 cout << "thread begin, thread id is :" << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(1000);//休息1秒 std::this_thread::sleep_for(dura); cout << "thread end" << endl; return 5; }); std::thread t1(std::ref(mypt), 1); t1.join(); std::future<int> result = mypt.get_future(); cout << result.get() << endl; */ /* //std::promise类模板,在某个线程中给它赋值,其他线程中可以使用 std::promise<int> myprom; std::thread t1(func,std::ref(myprom), 10); t1.join(); std::future<int> result = myprom.get_future(); auto res = result.get(); cout << "result : " << res << endl; cout << "结束" << endl; */ /* //4、 std::future<int> result = std::async(mythread,10); std::future_status status = result.wait_for(std::chrono::seconds(1));//等待1s返回枚举类型 if (status == std::future_status::timeout)//表示超时,线程未执行完 { cout << "超时,线程未执行完" << endl; } else if (status == std::future_status::ready)//表示线程成功返回 { cout << "线程执行完毕,返回" << endl; cout << result.get() << endl; } else if (status == std::future_status::deferred) { //async的第一个参数设置为std::launch::deferred cout << "线程延迟执行" << endl; cout << result.get() << endl; } */ /* //5、shard_future 类模板,get()复制数据,可以get多次 std::packaged_task<int(int)> mypt(mythread); std::thread t1(std::ref(mypt), 10); t1.join(); std::future<int> result = mypt.get_future(); bool isValid = result.valid(); if(isValid) cout<<"result valid"<<endl; std::shared_future<int> shared_res(result.share()); //等价于std::move(result) //上述5行可以代替为: //std::shared_future <int > res(mypt.get_future()); isValid = result.valid(); if (!isValid) { cout << "result unvalid" << endl; isValid = shared_res.valid(); cout << "get result :" << shared_res.get() << endl; cout << "get result :" << shared_res.get() << endl; cout << "get result :" << shared_res.get() << endl; } */ /* //6、原子操作std::atomic //全局变量num定义为atomic对象 thread t1(addNum); thread t2(addNum); t1.join(); t2.join(); cout << num << endl; */ return 0; }