语言级别的多线程编程
c++语言级别的多线程编程
通过语言级别的多线程编程可以使多线程代码跨平台运行
使用线程时尽量脱离
thread/mutex/condition_variable
lock_quead/unique_lock
atomic基于CAS操作的原子类型
睡眠sleep_for
多线程基础
#include<iostream>
#include<thread>
//this_thread是当前线程下的一个命名空间,用于调用该线程的一些基本信息和函数
//chrono也是一个std下的命名空间,里面有一些常见的时间函数
void threadHanler1(int seconds){
std::cout<<"Hello Thread"<<std::endl;
std::this_thread::sleep_for(std::chrono::seconds(seconds));
std::cout<<"GoodBye Thread"<<std::endl;
}
signed main(){
//定义了一个线程对象 , 传递了一个线程入口函数
//传入后新线程就开始运行了
std::thread t1(threadHanler1 , 1);
//主线程等待子进程继续之后就继续往下运行
t1.join();
//把子线程设置为分离线程
t1.detach();
std::cout<<"finish!"<<std::endl;
//主线程在运行结束的时候会检查所有子线程
//如果子线程不是分离线程,且未结束,就会抛出异常
return 0;
}
主线程在运行结束的时候会检查所有子线程
如果子线程不是分离线程,且未结束,就会抛出异常
线程互斥
如何防止死锁问题的发生:使用lock_guard和unique_lock
/*
* @Date: 2024-08-01 02:41:45
* @LastEditors: cosh
* @LastEditTime: 2024-08-08 15:23:14
* @FilePath: \c++\a.cpp
*/
#include<iostream>
#include<thread>
#include<list>
#include<mutex>
using namespace std;
/*
竞态条件:多线程程序执行的结果应该是一致的,不会随着CPU对线程不同的调用顺序,而产生不同的运行结果
*/
//模拟卖票程序(存在竞态条件)【使用互斥锁】
int ticketCount = 100;
std::mutex mtx;
//售票窗口
void sellTicket(int index){
while(ticketCount > 0){
//问题:如果在if中子线程异常退出,锁没有及时释放,导致死锁 -> 使用智能指针
//lock_guard 和 unique_lock
{
//lock_guard<std::mutex> lock(mtx); //有点像scored_ptr , ban了赋值和拷贝构造 , 会自动加锁(建议只用这个)
unique_lock<std::mutex> lock(mtx); //支持带右值引用的拷贝构造和赋值运算符重载
lock.lock();
if(ticketCount > 0){
cout<<"窗口"<<index<<"卖出第 : " << ticketCount <<"张票"<<endl;
ticketCount--;
}
lock.unlock();
} //新建一个作用域,出了作用域之后就自动析构掉了
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
signed main(){
list<std::thread> tlist;
for(int i = 1 ; i <= 3 ; i++){
tlist.push_back(std::thread(sellTicket , i));
}
for(std::thread &t : tlist){
t.join();
}
return 0;
}
基于CAS操作的atomic原子类型
互斥锁的操作是比较重的,临界区代码做的事情稍稍复杂
系统理论上:CAS来保证线面的++ --操作就足够了 CAS操作又称为无锁操作
面试题,如何实现一个无锁队列
利用CAS在硬件层面加锁
#include<iostream>
#include<thread>
#include<atomic>
#include<list>
using namespace std;
volatile std::atomic_bool isReady = false;
volatile std::atomic_int ticketCount = 0;
//防止子线程对对象进行缓存,保证变量一定是原始数据的值
void task(){
while(!isReady){
std::this_thread::yield(); //线程出让当前的CPU时间片,等待下一次调度
}
for(int i = 0 ; i < 100 ; i++){
ticketCount++;
}
}
signed main(){
list<std::thread> tlist;
for(int i = 1 ; i <= 10 ; i++){
tlist.push_back(thread(task));
}
std::this_thread::sleep_for(std::chrono::seconds(3));
isReady = true;
cout<<"ticketCount:"<<ticketCount<<endl;
for(std::thread &t : tlist) t.join();
}
c++线程间同步通信
多线程编程的两个问题:
线程间的互斥
竞态条件 -> 临界区代码段 -> 原子操作 -> 互斥锁mutex / 轻量级的无锁机制(CAS)
strace ./a.out -> pthread_mutex_t
线程间的同步通信
不通信的话就没有执行顺序可言,出问题的时候哪里复现
生产者,消费者线程模型
C++的所有容器都不是线程安全的
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
cosh'blog!
喜欢就支持一下吧