目录
1. 线程创建
1.1 创建函数作为线程工作函数
新建一个工作函数作为线程工作函数,然后在后面跟上工作函数的传入参数,如下:
#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;
}
1.2 创建匿名函数作为线程工作函数
#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;
//线程1调用increase函数
thread thread1(increase, &num, 100000);
thread thread2([&]() {//线程2使用匿名函数作为线程函数
for (int i = 0; i < 100000; i++)++num;
});
thread1.join();
thread2.join();
cout << num << endl;
return 0;
}
1.3 类成员函数作为线程工作函数
#include <iostream>
#include <thread>
using namespace std;
void increase(int *p, int times) {
for (int i = 0; i < times; i++)++(*p);
}
class Test {
public:
void increase(int *p, int times) {
for (int i = 0; i < times; i++)++(*p);
}
};
int main()
{
int num = 0;
//线程1调用increase函数
thread thread1(increase, &num, 100000);
thread thread2([&]() {//线程2使用匿名函数作为线程函数
for (int i = 0; i < 100000; i++)++num;
});
Test test;
thread thread3(&Test::increase, &test, &num, 100000);//类成员函数作为线程工作函数
thread1.join();
thread2.join();
thread3.join();
cout << num << endl;
return 0;
}
2. 线程互斥
2.1 使用mutex进行线程互斥
就是单纯的使用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;
}
2.2 使用lock_guard和mutex实现线程互斥
只是用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();
}
}
3. 其他功能函数
3.1 join和detach
多线程下可能出现当前主线程结束后,子线程仍未结束的情况,此时可以在主线程中调用子线程的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;
}
3.2 线程暂停
可以使用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));//线程暂停,直到某个时间
}
3.3 赋值运算符
VS下thread类的赋值运算符被禁用了,因此两个thread对象之间不能直接赋值,但是可以使用swap()方法将一个线程的控制权转移到另一个thread对象。
......
thread thread3;
thread3.swap(thread2);//使用swap()方法将thread2的控制权转移到thread3
......
thread3.join();//后面执行thread3的join()方法
......
参考: