临界区
include "stdafx.h"
include <windows.h>
CRITICAL_SECTION cs = {};
int g_nNum = 0;
DWORD WINAPI ThreadProc(LPVOID lParam) {
// 2. 进入临界区
// cs有个属性LockSemaphore是不是被锁定
// 当调用EnterCriticalSection表示临界区被锁定,OwningThread就是该线程
// 其他调用EnterCriticalSection,会检查和锁定时的线程是否是同一个线程
// 如果不是,调用Enter的线程就阻塞
// 如果是,就把锁定计数LockCount+1
// 有几次Enter就得有几次Leave
// 但是,不是拥有者线程的人不能主动Leave
EnterCriticalSection(&cs);
for (int i = 0; i < 100000; i++)
{
g_nNum++;
}
printf("%d\n", g_nNum);
// 3. 离开临界区
// 万一,还没有调用Leave,该线程就崩溃了,或死循环了..
// 外面等待的人就永远等待
// 临界区不是内核对象, 不能跨进程同步
LeaveCriticalSection(&cs);
return 0;
}
int main()
{
// 1. 初始化临界区
InitializeCriticalSection(&cs);
HANDLE hThread1 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
printf("%d\n", g_nNum);
// 4. 销毁临界区
DeleteCriticalSection(&cs);
return 0;
}
==================
互斥体
include "stdafx.h"
include <windows.h>
HANDLE hMutex = 0;
int g_nNum = 0;
// 临界区和互斥体比较
// 1. 互斥体是个内核对象,可以跨进程同步,临界区不行
// 2. 当他们的拥有者线程都崩溃的时候,互斥体可以被系统释放,变为有信号,其他的等待函数可以正常返回
// 临界区不行,如果都是假死(死循环,无响应),他们都会死锁
// 3. 临界区不是内核对象,所以访问速度比互斥体快
DWORD WINAPI ThreadProc(LPVOID lParam) {
// 等待某个内核对象,有信号就返回,无信号就一直等待
// 返回时把等待的对象变为无信号状态
WaitForSingleObject(hMutex, INFINITE);
for (int i = 0; i < 100000; i++)
{
g_nNum++;
}
printf("%d\n", g_nNum);
// 把互斥体变为有信号状态
ReleaseMutex(hMutex);
return 0;
}
int main()
{
// 1. 创建一个互斥体
hMutex = CreateMutex(
NULL,
FALSE,// 是否创建时就被当先线程拥有
NULL);// 互斥体名称
HANDLE hThread1 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
printf("%d\n", g_nNum);
return 0;
}
=====================
防多开
include "stdafx.h"
include <windows.h>
int main()
{
if (OpenMutex(SYNCHRONIZE, NULL, L"24期"))
{
// 说明互斥体存在,已经打开过一次程序
return 0;
}
HANDLE hMutex = CreateMutex(NULL, NULL, L"24期");
system("pause");
return 0;
}
===================
信号量
include "stdafx.h"
include <windows.h>
HANDLE hSemphore;
int g_nNum = 0;
DWORD WINAPI ThreadProc(LPVOID lParam) {
WaitForSingleObject(hSemphore, INFINITE);
for (int i = 0; i < 100000; i++)
{
g_nNum++;
}
printf("%d\n", g_nNum);
ReleaseSemaphore(hSemphore,
1,// 释放的信号个数可以大于1,但是释放后的信号个数+之前的不能大于最大值,否则释放失败
NULL);
return 0;
}
int main()
{
hSemphore = CreateSemaphore(
NULL,
1,// 初始信号个数
1,// 最大信号个数,就是允许同时访问保护资源的线程数
NULL);
HANDLE hThread1 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
printf("%d\n", g_nNum);
return 0;
}
=========================
事件
include "stdafx.h"
include <windows.h>
HANDLE hEvent1, hEvent2;
DWORD WINAPI ThreadProcA(LPVOID lParam) {
for (int i = 0; i < 10; i++){
WaitForSingleObject(hEvent1, INFINITE);
printf("A ");
SetEvent(hEvent2);
}
return 0;
}
DWORD WINAPI ThreadProcB(LPVOID lParam) {
for (int i = 0; i < 10; i++){
WaitForSingleObject(hEvent2, INFINITE);
printf("B ");
SetEvent(hEvent1);
}
return 0;
}
int main()
{
// 事件对象,高度自定义的
hEvent1 = CreateEvent(
NULL,
FALSE,// 自动重置
TRUE,// 有信号
NULL);
// hEvent1自动重置 初始有信号 任何人通过setevent变为有信号 resetevent变为无信号
// hEvent2自动重置 初始无信号
hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hThread1 = CreateThread(NULL, NULL, ThreadProcA, NULL, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProcB, NULL, NULL, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
return 0;
}
=================
双进程守护
include "stdafx.h"
include <windows.h>
int main()
{
HANDLE hEventA = CreateEvent(NULL, FALSE, TRUE, L"我是A");
HANDLE hEventB = NULL;
printf("我是A\n");
while (true)
{
hEventB = OpenEvent(SYNCHRONIZE, NULL, L"我是B");
if (!hEventB)
{
STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
if (!CreateProcess(L"..\Debug\06.双进程守护B.exe",
NULL, NULL, NULL, NULL, CREATE_NEW_CONSOLE, NULL,
NULL, &si, &pi))
return 0;
WaitForSingleObject(pi.hProcess, INFINITE);
Sleep(100);
}
else
{
CloseHandle(hEventB);
Sleep(200);
}
}
return 0;
}
include "stdafx.h"
include <windows.h>
int main()
{
HANDLE hEventB = CreateEvent(NULL, FALSE, TRUE, L"我是B");
HANDLE hEventA = NULL;
printf("我是B\n");
while (true)
{
hEventA = OpenEvent(SYNCHRONIZE, NULL, L"我是A");
if (!hEventA)
{
STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
if (!CreateProcess(L"..\Debug\05.双进程守护A.exe",
NULL, NULL, NULL, NULL, CREATE_NEW_CONSOLE, NULL,
NULL, &si, &pi))
return 0;
WaitForSingleObject(pi.hProcess, INFINITE);
//Sleep(100);
}
else
{
CloseHandle(hEventA);
}
}
return 0;
}