目录html
参考:ios
http://www.javashuo.com/article/p-fofmzcap-hk.htmlc++
https://en.cppreference.com/w/git
https://wizardforcel.gitbooks.io/cpp-11-faq/content/77.html编程
http://www.cplusplus.com/reference/promise
C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是
#include <bits/stdc++.h> #include <thread> using namespace std; void function_name() { cout << "hello world" << endl; } int main() { std::thread t(function_name); t.join(); return 0; }
std::thread 构造并发
注意:可被 joinable 的 thread 对象必须在他们销毁以前被主线程 join 或者将其设置为 detached.异步
其余函数async
get_id | 获取线程ID |
---|---|
joinable | 检查线程是否能够join |
join | join线程 |
detach | detach线程 |
swap | swap线程 |
native_handle | 返回native_handle |
hardware_concurrency[static] | 检查硬件并发性 |
参考:https://en.cppreference.com/w/cpp/thread/thread/thread
#include <iostream> #include <utility> #include <thread> #include <chrono> void f1(int n) { for (int i = 0; i < 5; ++i) { std::cout << "Thread 1 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } void f2(int& n) { for (int i = 0; i < 5; ++i) { std::cout << "Thread 2 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } class foo { public: void bar() { for (int i = 0; i < 5; ++i) { std::cout << "Thread 3 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } int n = 0; }; int main() { int n = 0; foo f; std::thread t1; // t1 is not a thread std::thread t2(f1, n + 1); // pass by value std::thread t3(f2, std::ref(n)); // pass by reference std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f t2.join(); t4.join(); t5.join(); std::cout << "Final value of n is " << n << '\n'; std::cout << "Final value of foo::n is " << f.n << '\n'; }
Thread 1 executing Thread 2 executing Thread 3 executing Thread 3 executing Thread 1 executing Thread 2 executing Thread 2 executing Thread 3 executing Thread 1 executing Thread 3 executing Thread 2 executing Thread 1 executing Thread 3 executing Thread 1 executing Thread 2 executing Final value of n is 5 Final value of foo::n is 5
std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
保留疑惑,函数名便是地址,加&仍是地址,可是看别人怎么写。
move (1) | thread& operator= (thread&& rhs) noexcept; |
---|---|
copy [deleted] (2) | thread& operator= (const thread&) = delete; |
Mutex 系列类(四种)
Lock 类(两种)
其余类型
函数
并发最大的问题就是对临界区资源的访问,主要是经过互斥量上锁的方法解决。
http://www.cplusplus.com/reference/mutex/mutex/try_lock/ 具体细节看库便可,下面解析一些常见的
主要用unique_lock,在构造函数上锁,在析构函数解锁,第一个参数为互斥量,第二个是可选
https://en.cppreference.com/w/cpp/thread/lock_tag
#include <bits/stdc++.h> using namespace std; int main() { std::mutex my_mutex; std::unique_lock<std::mutex> lock(my_mutex); ///表示这个互斥量已经lock成功了,通知构造函数不用在lock了, my_mutex.lock(); ///必须先lock才能用 std::unique_lock<std::mutex> lock1(my_mutex, std::adopt_lock); ///后面会本身unlock() ///============================ ///尝试锁,没锁成功不阻塞, 前提互斥量不能被锁定 std::unique_lock<std::mutex> lock2(my_mutex, std::try_to_lock); if(lock.owns_lock()) { ///拿到了锁头 } else { ///没有拿到锁头 } ///============================ ///我没加锁,后面手动锁,方便调用函数, 前提互斥量不能被锁定 std::unique_lock<std::mutex> lock3(my_mutex, std::defer_lock); lock3.lock(); ///加锁 lock3.unlock(); ///不加锁 if(lock3.try_lock() == true) { ///拿到锁头了 } else { ///没拿到 } ///释放互斥量 std::mutex *m = lock3.release(); return 0; }
一个线程等待另外一个线程条件知足
void function_name() { unique_lock<mutex> lock(mutex1); ///能往下走,确定互斥量默认被锁了,到wait。 ///第二个参数可选,没写默认false。true为不堵塞,继续走。 ///若是是false卡在这等待其余线程的con.notify_one()的函数 ///注意notify_one的时候必须卡在wait的地方,不然唤醒失败 ///notify_all() con.wait(lock, [] () { if(true) { return true; } return false; }); }
std::async启动一个异步任务后,返回一个std::future访问异步操做结果的机制
#include <bits/stdc++.h> #include <future> using namespace std; int mythread() { cout << "mythread = " << this_thread::get_id() << endl; return 5; } int main () { cout << "main = " << this_thread::get_id() << endl; ///压根没建立子线程,在主线程中作,视乎默认是这个 std::future<int>ret = std::async(std::launch::deferred, mythread); ///async 新线程在这里开始 std::future<int>ret = std::async(std::launch::async, mythread); cout << ret.get(); ///卡在这里等结果 return 0; }
用packaged_task打包线程,就多了一个能够返回结果的future接口
#include <bits/stdc++.h> #include <future> #include <thread> using namespace std; int mythread() { cout << "mythread = " << this_thread::get_id() << endl; return 5; } int main () { ///std::packaged_task 打包可调用对象 std::packaged_task<int()>mypt(mythread); std::thread t1(std::ref(mypt)); t1.join(); std::future<int>res = mypt.get_future(); return 0; }
后续就能够这么用
/// vector<std::std::packaged_task<int()>> vec; ///不用移动语义可能会出问题 vec.push_back(std::move(mypt));