C++ thread 那点事

萝らか妹 提交于 2019-12-16 18:09:01

1. C++ 线程通过thread th(func)或者thread *th=new thread(func)建立;建立线程后,记得在作用域内调用join或detach,否则退出作用域后程序会异常退出;其中join表示阻塞主线程在join处,等待子线程结束后再继续;detach表示主线程与子线程分离,独立运行;

2. mutex(互斥锁)用于在多个线程访问同一资源时,保证数据的一致性(lock/unlock),lock后,其他线程将阻塞在lock处,直到unlock;

3. 如果mutex多次lock,第二次会阻塞在lock处,直到unlock;C++提供了try_lock()防止阻塞;

4. 可以使用 lock_guard自动加锁、解锁。原理是 RAII,和智能指针类似或者使用 unique_lock自动加锁、解锁
unique_lock与 lock_guard原理相同,但是提供了更多功能(比如可以结合条件变量使用),unique_lock和lock_guard都是管理锁的辅助类工具,都是RAII风格;它们是在定义时获得锁,在析构时释放锁。mutex::scoped_lock其实就是 unique_lock<mutex> 的 typedef。

5.RAII(Resource Acquisition Is Initialization),也称直译为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的机制。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。 (个人认为可以理解为一个栈对象,当离开作用域后,析构函数调用解锁(智能指针则调用delete));

6.可以通过花括号{ }指定unique_lock的作用域(C++);

7.在C++11中,可以使用条件变量(condition_variable)实现多个线程间的同步操作;当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些线程才会被唤醒;

8.在条件变量中只能使用std::unique_lock<std::mutex>

9.线程的阻塞是通过成员函数wait()/wait_for()/wait_until()函数实现的,wait函数会在阻塞时,自动释放锁权限,即调用unique_lock的成员函数unlock(),以便其他线程能有机会获得锁;

10.std::condition_variable::notify_one() 唤醒某个等待wait线程。假设当前没有等待线程,则该函数什么也不做,假设同一时候存在多个等待线程,则唤醒某个线程是不确定的

11.std::condition_variable::notify_all() 唤醒全部的等待(wait)线程;

下面是摘自博客https://murphypei.github.io/blog/2019/04/cpp-concurrent-3.html的一个例子:

//单生产者-单消费者模型
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<queue>
#include<chrono>
#include<atomic>
int main()
{
	std::queue<int> production;
	std::mutex mtx;
	std::condition_variable cv;
	bool ready = false;  // 是否有产品可供消费
	bool done = false;   // 生产结束

	std::thread producer
	(
		  [&]()->void    //匿名函数
	      {
			  for (int i = 1; i < 10; ++i)
			  {
				  std::this_thread::sleep_for(std::chrono::milliseconds(10));//休眠10ms
				  std::cout << "producing" << i << std::endl;
				  std::unique_lock<std::mutex> lock(mtx);
				  production.push(i);
				  // 有产品可以消费了
				  ready = true;
				  cv.notify_one();
			  }
			  //生产结束了
			  done = true;
	      }
	);

	std::thread consumer
	(
	    [&]()->void
	    {
			std::unique_lock<std::mutex> lock(mtx);
			// 如果生成没有结束或者队列中还有产品没有消费,则继续消费,否则结束消费
			while (!done || !production.empty())//防止阻塞在wait处
			{
				while (!ready)
					cv.wait(lock);
				while (!production.empty())
				{
					std::cout << "consuming " << production.front() << std::endl;
					production.pop();
				}
				// 没有产品了
				ready = false;
			}
	    }
	);

	producer.join();
	consumer.join();
	//int a = 1;
	//{
	//	int *p = &a;//花括号可以指定作用域
	//}
	return 0;
}

这个例子用到了C++匿名函数,可以查看博客https://www.cnblogs.com/pzhfei/archive/2013/01/14/lambda_expression.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!