多线程,并发安全与volatile

多线程,并发安全与volatile

本文可能涉及到的一些知识,std::thread,线程同步互斥量,线程通信条件变量,线程安全的院子变量,call_once,异步操作,线程安全

volatile类型修饰符(类型修饰符:例如const)

(用于修饰被不同线程访问和修改的变量,作为指令关键字,确保本条指令不会因为编译器的优化而省略,且要求每次直接读值)

例如:并行设备的硬件寄存器,一个中断服务子程序中会访问到的非自动变量,多线程应用中被几个任务共享的变量

使用:volatile int a;



线程的生存周期

new->runable->running->blocked->time waiting->waiting->dead



线程类型形式(include”thread” env(C++))

创建线程

std::thread t(func,param1,param2);
(仍可容易创建形如bind()与lambda线程函数)
//实际上并不喜欢这种创建之后直接执行的线程形式,或者是我了解不够,在JAVA中此类得到了改善,拥有独立的start()

线程操作

阻塞(即等待线程完结):t.join();    
    reload->t.join(long millis)    t.join(long millis,int nanoseconds)

分离线程:t.detach();        //生命周期不可预计    

移动线程:std::thread t1(std::move(t));

取得线程ID:std::this_thread::get_id()   

等待:std::this_thread::sleep_for(chrono)

线程的WINAPI形式(由微软在Windows API中提供)

创建新线程

MSDN中CreateThread原型:

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//指向SECURITY_ATTRIBUTES形态的结构指针
SIZE_T dwStackSize,//initialstacksize   //初始栈大小空间,0为与函数的线程大小相同的栈
LPTHREAD_START_ROUTINE lpStartAddress,//ThreadPoint 声明形式:DWORD WINAPI function(LPVOID lpParam)
/*
可选择参数类型void:
lpStartAddress:(LPTHREAD_START_ROUTINE)Myvoid
线程声明:
void Myvoid()
{
  return;
}
*/
LPVOID lpParameter,//threadParam
DWORD dwCreationFlags,//CREATE_SUSPENDED/0/STACK_SIZE_PARAM_IS_A_RESERVATION
LPDWORD lpThreadId//threadidentifier
)

processthreadsapi.h中CreateThread原型:

WINBASEAPI
_Ret_maybenull_
HANDLE WINAPI CreateThread(
_In_opt_LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_SIZE_T dwStackSize,
_In_LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt___drv_aliasesMemLPVOID lpParameter,
_In_DWORD dwCreationFlags,
_Out_opt_LPDWORD lpThreadId
);

关闭线程

Bool CloseHandle(HANDLE hObject);
(可用于关闭多种具有句柄的对象)


常见的其他线程开始关闭对

RTL库System单元

BeginTHread()

MFC

AfxBeginThread()

Visual C++

_beginThread()
_endThread()



事件

(通过通知操作的方式保持线程同步,并可以实现不同进程中的线程同步操作

相关函数

 CreateEvent()    //创建一个信号量
 OpenEvent()    //打开一个事件
 SetEvent()   //回置事件
 WaitForMultipleObject()    //等待一个事件
 WaitForMultipleObjects(IN DWORD nCount,    //等待句柄数
                        IN CONST HANDLE* IpHandles,   //指向句柄数组
                        IN BOOL bWaitAll,   //是否完全等待标志
                        IN DWORD dwMilliseconds)     //等待时间
                        //等待多个事件return(超时)WAIT_TIMEOUT)
 ```
****
****
## 信号量
(信号允许多个线程同时使用共享资源(如同操作系统中的PV操作),同时指出了同时访问的最大量(最大资源计数))
### 线程操作

CreateSemaphone() //创建一个信号量
OpenSemaphone() //打开一个信号量(同加锁)
ReleaseSemaphone() //释放信号量(同解锁)
WaitForSingleObject() //等待信号量(同延时锁)
(进程与线程在退出前处于无信号状态,在退出后会处于有信号状态,可以使用WaitForSIngleObject()来等待进程和线程退出)

****
****
## 临界区
(提供独占式访问,工作于用户级)    
### 相关函数

void InitializeCriticalSection(LPCRITICAL_SECTION IpCriticalSection) //初始化临界区

void EnterCriticalSection(LPCRITICAL_SECTION IpCriticalSection) //进入临界区

void LeaveCriticalSection(LPCRITICAL_SECTION IpCriticalSection) //离开临界区

void DeleteCriticalSection(LPCRITICAL_SECTION IpCriticalSection) //释放临界区资源

(临界区使用为防止失误常使用封装的方式进行,以对象的生命周期控制临界区范围)
****
****
## 互斥量--`<mutex>`
(一种同步原语,线程同步手段,保护多线程同时访问的共享数据,互斥量的争夺实际上就是对其所有权的争夺,线程优先级影响争夺线程的结果,可以命名,标志着可以跨进程使用)    
分类:   
**std::mutex:独占互斥量,不能递归使用**    

**std::timed_mutex:具有超时的独占互斥量,不能递归使用**   
(递归锁定复杂度高,效率低下爱,并非不可优化,且有未标明的最大次数限制)

**std::recursive_mutex:递归互斥量(允许统一线程多次获得同一互斥量),不具有超时**    

**std::recursive_timed_mutex:不做解释**   

(ps:4种互斥量在循环中除mutex均不会产生join())
### 基本操作

lock()
unlock()
try_lock()
timed_mutex::try_lock_for(chrono)


### RAII技术*lock_guard/unique_lock
std::lock_guard<std::mutex> locker(g_lock);  //出作用域自动解锁(析构)  
std::unique_lock<std::mutex> locker(g_lock);  //可随时释放线程锁,而非需要等待对象生命周期结束

### 条件变量--`<condition_variable>`
**condition_variable,配合std::unique_lock<std::mutex>进行wait()操作**   
std::unique_lock()--可以自由的释放mutex而非需要等待对象生命周期结束    

**condition_variable_any,和任意带有lock(),unlock()语义的mutex搭配使用,比较灵活但是效率较差**    

含有函数:   
  condition_variable::wait(std::mutex)  
  (该函数接受重载:condition_variable::wait(mutex,lambda/function*))  

  (唤起线程)condition_variable::notify_one()/notify_all()   

### 原子变量--`atomic`    
类型说明:std::atomic<T>
--读取修改会写变为不可打断的操作   

usual_use--`atomic::load()`
(return Value)    
****
### call_once/once_flag的使用
(保证多线程环境中函数仅被调用一次)    
>std::call_once(`once_flag`,`Funtion`);
(once_flag设置作用于决定该独有性的区间)

****
****
## 异步操作
### 异步操作类
#### std::future
(使用同步等待的方式来获取异步操作的结果)   
Get:

get() //等待并返回结果
wait() //等待
wait_for(std::chrono) //超时等待返回结果

Return:
Deferred    //异步操作还未开始
Ready   //已完成
Timeout   //异步操作超时
**future本身不渴拷贝,shared_future则可以拷贝放入容器**

****
#### std::promose
(绑定数据和future,线程将为外部传入(参数)的promise赋值)    
Get:

std::promise ptr;
std::thread t(std::promise& p)
{p.set_value_at_thread_exit(9);},std::ref(ptr));
std::future f= ptr.get_future();
auto r=f.get();


****
#### std::package_task
(包装了一个可以调用对象的包装类,将函数和future绑定起来)    
Get:

std::packaged_task

### 异步操作函数async
(async比future,packed_task,thread等更高一级,可以直接创建异步的task,异步任务的返回结果也保存在future中)
>**async(std::launch::async|std::launch::deffered,f,args...)**    
param:    
创建线程的策略   
    std::launch::async  //在调用async时就创建线程
    std::launch::deffered  //延迟加载方式创建线程————直到调用了future的get或者wait时才创建线程
线程函数
线程函数参数    

“`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值