C++——多线程

目录

 

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 赋值运算符


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()方法
    ......

参考:

C++11多线程(简约但不简单)

浅谈C++中的多线程(一)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值