1. 互斥
利用互斥对象可以实现多个线程对某资源的互斥访问,互斥对象是内核对象,包含以下组成部分:一个线程ID(当前拥有该互斥对象的线程)、一个计数器(线程拥有互斥对象的次数)和一个使用计数。
对于互斥对象的使用有一条原则:谁拥有谁释放。
1)创建互斥对象
事件内核对象包含:使用计数,自动重置还是人工重置,状态。
对于人工重置事件当某等待此事件的线程变为可调度后不会把该事件从有信号状态设为无信号状态,所以对于人工重置事件应在被保护代码前调用ResetEvent将事件设为无信号状态,在被保护代码后调用SetEvent将事件设为有信号状态。
对于自动重置事件当等待该事件的线程中有一个变为可调度时OS会自动将该事件设为无信号状态,所以在自动重置事件所保护的代码后应调用SetEvent将事件设为有信号状态。
1)创建事件对象
3.关键区
关键区是线程中访问共享资源的代码段。
1)创建关键区
4.总结
利用内核对象(互斥对象和事件对象)完成线程同步速度慢,但可以在多个进程的各个线程间同步;
关键区工作在用户态,速度较快但容易产生死锁。
利用互斥对象可以实现多个线程对某资源的互斥访问,互斥对象是内核对象,包含以下组成部分:一个线程ID(当前拥有该互斥对象的线程)、一个计数器(线程拥有互斥对象的次数)和一个使用计数。
对于互斥对象的使用有一条原则:谁拥有谁释放。
1)创建互斥对象
HANDLE CreateMutex{2)请求拥有互斥对象
LPSECURITY_ATTRIBUTES lpMutexAttributes, //Pointer to SECURITY_ATTRIBUTES, always NULL
BOOL bInitialOwner, //创建线程创建后是否拥有该互斥对象
LPCTSTR lpName //互斥对象名
}
DWORD WaitForSingleObject(3)释放拥有的互斥对象
HANDLE hHandle, //所请求对象的句柄
DWORD dwMilliseconds //等待时间
)
BOOL ReleaseMutex(HANDLE hMutex)4)利用互斥对象保证应用程序同一时刻只有一个实例运行
void main(){2.Event
singleMutex = CreateMutex(NULL, TRUE, "single");
if(singleMutex){
if(GetLastError() == ERROR_ALREADY_EXISTS){
输出:程序已经有一个实例在运行!
return;
}
}
}
事件内核对象包含:使用计数,自动重置还是人工重置,状态。
对于人工重置事件当某等待此事件的线程变为可调度后不会把该事件从有信号状态设为无信号状态,所以对于人工重置事件应在被保护代码前调用ResetEvent将事件设为无信号状态,在被保护代码后调用SetEvent将事件设为有信号状态。
对于自动重置事件当等待该事件的线程中有一个变为可调度时OS会自动将该事件设为无信号状态,所以在自动重置事件所保护的代码后应调用SetEvent将事件设为有信号状态。
1)创建事件对象
HANDLE CreateEvent(2)将事件对象设为有信号、无信号状态
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
)
BOOL SetEvent(HANDLE hEvent)4)利用事件对象保证应用程序同一时刻只有一个实例运行
BOOL ResetEvent(HANDLE hEvent)
void main(){为了实现线程间同步就使用自动重置事件,因为线程在ResetEvent执行前有可能被抢占。
HANDLE sigleEvent = CreateEvent(NULL, FALSE, FALSE, "single");
if(sigleEvent ){
if(GetLastError() == ERROR_ALREADY_EXISTS){
输出:程序已经有一个实例在运行!
return;
}
}
}
3.关键区
关键区是线程中访问共享资源的代码段。
1)创建关键区
void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)2)访问关键区
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)3)离开关键区
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)4)释放关键区
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
4.总结
利用内核对象(互斥对象和事件对象)完成线程同步速度慢,但可以在多个进程的各个线程间同步;
关键区工作在用户态,速度较快但容易产生死锁。