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
来源:CSDN
作者:雨后森林cy
链接:https://blog.csdn.net/xysjj/article/details/103565473