C++ thread 那点事

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

C++ 中,`<thread>` 头文件提供了用于多线程编程的相关类和函数。可以使用 `std::thread` 类来创建和管理线程。 以下是一个简单的示例代码,演示了如何使用 `std::thread` 创建并执行一个线程: ```cpp #include <iostream> #include <thread> // 线程函数,接收一个整数参数 void threadFunction(int threadId) { std::cout << "Hello from thread " << threadId << std::endl; } int main() { // 创建一个线程,并指定线程函数和参数 std::thread t(threadFunction, 1); // 等待线程执行完毕 t.join(); return 0; } ``` 在上述代码中,我们定义了一个名为 `threadFunction` 的线程函数,它接收一个整数参数 `threadId`。主函数中,通过 `std::thread` 类创建了一个新的线程 `t`,并指定线程函数为 `threadFunction`,传递参数 `1`。然后,通过调用 `t.join()` 来等待线程执行完毕。 运行上述代码,将输出 "Hello from thread 1"。 除了 `join()` 函数外,还可以使用 `detach()` 函数来分离线程。分离后的线程将在后台运行,主线程不会等待它的结束。 另外,C++11 还提供了其他一些线程相关的功能,如互斥量(`std::mutex`)、条件变量(`std::condition_variable`)和原子操作(`std::atomic`),用于实现线程间的同步和协调。这些功能可以帮助处理共享资源的并发访问和线程间的通信。 需要注意的是,在使用多线程编程时,需要小心处理线程间的竞态条件和资源同步,以避免数据竞争和未定义行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值