windows锁
临界区:InitializeCriticalSection() / EnterCriticalSection() / LeaveCriticalSection() / DeleteCriticalSection()
互斥锁:CreateMutex() / OpenMutex() / ReleaseMutex (有名字,可以被不同进程使用,获取锁和释放锁的必须是同一个线程)
信号量:CreateSemaphore() / OpenSemaphore() / ReleaseSemaphore (可以保护多个资源。可以被不同的thread加锁解锁)
event对象:main thread 进行event设置和操作:CreateEvent() / SetEvent() / WaitForMultiObjects() / CloseHandle() normal thread等待event: WaitForSingleObject()(在tread获得锁的使用权之前main thread要调用SetEvent设置一把)
使用频率:信号量 > 互斥区 > 临界区 > event
使用c++特性将EnterCriticalSection() 函数放入类的构造函数中,将LeaveCriticalSection() 放入类的析构函数中,可以实现实例创建时自动进行临界区pk,实例被各种情况销毁时撤销锁
原子锁(InterLocked)
嵌套锁(解决在申请使用公共数据时,数据自身带加锁机制导致使用的调用程序重复加锁造成的获取资源失败的情况)
//嵌套锁结构
typedef struct _NestLock //嵌套锁结构
{
int threadId; //上锁进程号
int count; //锁数量
HANDLE hLock; //锁信号量
}NestLock;
实现:
( NestLock *) create_nest_lock(HANDLE hLock) //嵌套锁create
{
NestLock *hNestLock;
hNestLock = (NestLock*)malloc(sizeof(NestLock));
assert( NULL != hNestLock );
hNestLock->threadId = hNestLock->count = 0;
hNestLock->hLock = hLock;
return hNestLock;
}
void get_nest_lock( NestLock *hNestLock) //申请嵌套锁
{
assert(NULL != hNestLock);
if( hNestLock->threadId == GetThreadId() ) //资源已被锁并且被当前线程锁,走嵌套锁流程
{
hNestLock->count ++;
}else{ //资源没被锁或被其他线程锁,走正常申请锁流程
WaitForSingleObject( hNestLock->hLock );
hNestLock->count = 1;
hNestLock->threadId = GetThreadID();
}
}
void release_nest_lock( NestLock *hNestLock ) //释放嵌套锁
{
assert( NULL != hNestLock );
assert( GetThreadId() == hNestLock->threadId );
hNestLock->count--;
if( 0 == hNestLock->count ) //当前为资源上的最后一个锁
{
hNestLock->threadId = 0;
ReleaseMutex( hNestLock->hLock );
}
}
无锁队列(队列具有天生的互斥性能)
队列先入先出的机制具有先天的互斥性能,一个线程入队列操作,一个线程出队列操作并不会对队列中内容造成混乱
如可以将队列作为job队列进行多进程任务分配
读写锁(多读少写的情况下,读读锁不互斥,写写锁互斥,读写锁互斥)
typedef struct _RWlOCK
{
int count; //锁数量
int state; //枚举类型(读,写,无锁)
HANDLE hRead; //读锁信号量
HANDLE hWrite; //写锁信号量
}RWLock;
typedef enum //枚举类型用来记录锁状态
{
STATE_EMPTY = 0, //没有锁
STATE_READ, //读锁
STATE_WRITE //写锁
};
获取读锁操作:wait for读锁信号量 -> wait for写锁信号量,修改锁状态为STATE_READ( 如果是第一次得到读锁 ) -> count++ -> 释放读锁信号量
获取写锁操作:申请写锁 -> count++ ->修改写锁状态为STATE_READ
释放读锁(和获取读锁对应):申请读锁 -> count-- ->修改锁状态为STATE_EMPTY , 释放写锁信号(如果是最后一把读锁) -> 释放读锁信号
顺序锁(对读写锁进行改进,解决读锁导致写锁一直等待的问题)
读锁不对信号量进行任何操作,通过sequence进行读锁的使用,有可能边写边读
无锁链表(对顺序锁的改进,解决处理的数据不能为指针的问题)
线程池(一次申请多个线程,通过任务队列进行调度,线程池中的线程一次init,中间只有启用和回收,进程结束统一销毁线程池,缓解了线程频繁创建和销毁造成的时间浪费)