目录
1. 线程创建
1.1 创建函数作为线程工作函数
1.2 创建匿名函数作为线程工作函数
1.3 类成员函数作为线程工作函数
2. 线程互斥
2.1 使用mutex进行线程互斥
2.2 使用lock_guard和mutex实现线程互斥
3. 其他功能函数
3.1 join和detach
3.2 线程暂停
3.3 赋值运算符
新建一个工作函数作为线程工作函数,然后在后面跟上工作函数的传入参数,如下:
#include <iostream> #include <thread> using namespace std; void increase(int *p, int times) { for (int i = 0; i < times; i++)++(*p); } int main() { int num = 0; //线程调用increase函数 thread thread1(increase, &num, 100000); thread thread2(increase, &num, 100000); thread1.join(); thread2.join(); cout << num << endl; return 0; }就是单纯的使用mutex执行lock和unlock,也可以使用try_lock让线程在共享资源被锁住的情况下不阻塞。
#include <iostream> #include <mutex> #include <thread> using namespace std; void increase(int *p, int times, mutex& m_mutex) { for (int i = 0; i < times; i++) { m_mutex.lock();//使用lock,如果当前已经被锁上,线程阻塞 ++(*p); m_mutex.unlock(); } } int main() { int num = 0; mutex m_mutex; //线程1调用increase函数 thread thread1([&]() { increase(&num, 1000000, m_mutex); }); thread thread2([&]() { for (int i = 0; i < 1000000; i++) { bool res = true; res = m_mutex.try_lock();//尝试加锁,如果已经被锁上,返回false,否则加锁并返回true if (res) {//如果没有被锁上,加锁并返回true ++num; m_mutex.unlock(); } else { cout << "1 " << endl; i--; } } }); thread1.join();//join是一个阻塞函数,主线程要等待子线程结束才能继续运行 thread2.join(); //detach():主线程不用等待子线程执行结束,二者脱离关系,常用于守护线程 cout << num << endl; return 0; }只是用mutex的话需要手动lock和unlock,使用lock_guard进行锁管理,虽然消耗了一点资源,但是编程更加方便,只改一下increase函数即可。
void increase(int *p, int times, mutex& m_mutex) { for (int i = 0; i < times; i++) { lock_guard<mutex> lk(m_mutex); //m_mutex.lock();//使用lock,如果当前已经被锁上,线程阻塞 ++(*p); //m_mutex.unlock(); } }多线程下可能出现当前主线程结束后,子线程仍未结束的情况,此时可以在主线程中调用子线程的join()方法,手动阻塞当前子线程,等到当前线程结束后,主线程才继续。
detach()方法则是将子线程从当前线程中分离出去,之后主线程就失去了对当前线程的控制权,无法调用线程的join()方法。可以通过joinable()方法查看当前线程是否还拥有对该线程的控制权。
#include <iostream> #include <mutex> #include <thread> #include <chrono> using namespace std; using namespace std::chrono; void increase(int *p, int times, mutex& m_mutex) { for (int i = 0; i < times; i++) { //m_mutex.lock();//使用lock,如果当前已经被锁上,线程阻塞 lock_guard<mutex> lk(m_mutex); ++(*p); //m_mutex.unlock(); } } int main() { int num = 0; mutex m_mutex; //线程1调用increase函数 thread thread1([&]() { increase(&num, 1000000, m_mutex); }); thread thread2([&]() { for (int i = 0; i < 1000000; i++) { bool res = true; res = m_mutex.try_lock();//尝试加锁,如果已经被锁上,返回false,否则加锁并返回true if (res) {//如果没有被锁上,加锁并返回true ++num; m_mutex.unlock(); } else { cout << "1 " << endl; i--; } } }); thread1.detach();//thread1.detach()之后,就不能对thread1执行join操作了 bool res = thread1.joinable(); if (res) { thread1.join(); } //thread1.join();//join是一个阻塞函数,主线程要等待子线程结束才能继续运行 thread2.join(); //detach():主线程不用等待子线程执行结束,二者脱离关系,常用于守护线程 cout << num << endl; return 0; }可以使用C++2.0提供的std::this_thread::sleep_for使线程暂停一段时间;使用std::this_thread::sleep_until使线程暂停直到指定时间。
void increase(int *p, int times, mutex& m_mutex) { for (int i = 0; i < times; i++) { //m_mutex.lock();//使用lock,如果当前已经被锁上,线程阻塞 lock_guard<mutex> lk(m_mutex); ++(*p); //m_mutex.unlock(); } this_thread::sleep_for(milliseconds(500));//线程暂停500毫秒 this_thread::sleep_until(system_clock::now() + milliseconds(500));//线程暂停,直到某个时间 }VS下thread类的赋值运算符被禁用了,因此两个thread对象之间不能直接赋值,但是可以使用swap()方法将一个线程的控制权转移到另一个thread对象。
...... thread thread3; thread3.swap(thread2);//使用swap()方法将thread2的控制权转移到thread3 ...... thread3.join();//后面执行thread3的join()方法 ......参考:
C++11多线程(简约但不简单)
浅谈C++中的多线程(一)