临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
互斥量:为协调共同对一个共享资源的单独访问而设计的。
信号量:为控制一个具有有限数量用户资源而设计。
事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
临界区:
临界区最大线程是64.
一般情况下,使用多线程都会使用CPP,因为CPP中有临界区结构.
同时操作单一元素很容易产生冲突,这种时候就需要定义临界区.
*临界区不是一个变量,而是调用操作系统,锁定当前变量.
使用临界区需要使用CreateThread来创建线程.
定义临界区:
CRITICAL_SECTION cs;//临界区
原型:
struct CRITICAL_SECTION
{
LONG lockCount;
LONG RecursionCount;
HANDLE OwningThread;
HANDLE LockSemaphore;
ULONG_PTR SpinCount;
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
InitializeCriticalSection(&cs); //初始化
EnterCriticalSection(&cs); //进入临界区
//... 变量操作内容
LeaveCriticalSection(&cs);//离开临界区
DeleteCriticalSection(&cs); //删除临界区
事件:
createEvent(); //创建事件
HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa, //安全描述符,瞧,这是个内核对象
BOOL fManualReset,
BOOL fInitialState,
PCTSTR pszName);
fManualReset参数为TRUE时,表示创建一个人工重置的时间,为FALSE时表示创建一个自动重置事件。
fInitialState参数为TRUE时,指明该事件是要初始化为已通知状态,反之为未通知状态。
pszName 时间名称
OpenEvent(EVENT_ALL_ACCSEE,true,name); //打开事件
HANDLE OpenEvent(
DWORD fdwAccess,
BOOL fInherit,
PCTSTR pszName);
pszName 时间名称
SetEvent(); //设置信号启用
ResetEvent(); //复位信号
实例:
HANDLE event[3] = {0}; //事件
HANDLE hthread[3] = {0}; //线程
DWORD WINAPI firstthread(void *p)
{
SetEvent(event[0]);
return 0;
}
DWORD WINAPI secondthread(void *p)
{
WaitForSingleObject(event[0], INFINITE);// 等待信号
//...
ResetEvent(event[0]);
return 0;
}
void main()
{
//创建事件
event[0] = createEvent(NULL, TRUE, FLASH, NULL);
event[1] = createEvent(NULL, TRUE, FLASH, NULL);
hthread[0] = CreateThread(NULL, 0, firstthread, NULL, 0, NULL);
hthread[1] = CreateThread(NULL, 0, secondthread, NULL, 0, NULL);
WaitForMultipleObjects(2, hthread, true, INFINI);
printf("全部完成\n");
system("pause");
}
互斥量:
CreateMutex(); //创建互斥量
CreateMutex(NULL, FALSH, NULL);
参数1: 安全机制
参数2: 是否激活
ReleaseMutex(mutex); //注销互斥量
OpenMutex(MUTEX_ALL_ACCESS, TRUE, name); 打开互斥量
实例:
HANDLE mutex= NULL;
DWORD WINAPI add(void *p)
{
WaitForSingleObject(mutex, INFINITE);
int i = 0;
while(++i != 101)
{
num++;
}
ReleaseMutex(mutex);
}
void main()
{
mutex = CreateMutex(NULL, Flash, NULL);
HANDLE hd[64];
int i;
for (i = 0, i < 64; i++)
{
hd[i] = CreadThread(NULL, 0, add, NULL, 0, NULL);
}
WaitForMultipleObjects(64, hd, true, INFINITE);
for (i = 0, i < 64; i++)
{
CloseHandle(hd[i]);
}
system("pause");
}
原子操作:
原子操作可以理解为在寄存器中直接操作,速度快,可以避免多线程中的一些问题
原子操作的速度要快于互斥量,临界区,event
InterlockedIncrement(&num); //变量++操作
InterlockedExchangeAnd(&num, 1); //num++
InterlockedDecrement(&num); //num--
InterlockedExchange(); //改变
InterlockedAnd(&num, 1); // num + 1
时间同步:
单独定时器只能用在同步通信
SetWaitablesTimer(timer, &time, 0, NULL, 0 NULL)
参数3: 多少毫秒一次
参数4: 回调函数
参数5: 参数
回调函数声明格式:
//参数2与参数3是时差
void CALLBACK timerun(viod *parg, DWORD timeaeg, DWORD timehigh)
{
}
CamcelWaitableTimer(timer);//取消定时器
定时器:
//创建定时器
HANDLE timer = CreateWaitableTimer(NULL, TRUE, 'name');
if (timer == NULL)
return 0;
LARGE_INTEGER time; //可精确到小数点后7位
time.Quadpart = -2000000 // 2秒
SetWaitablesTimer(timer, &time, 0, NULL, 0 NULL);//设置定时器等待
if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0)
{
print("等待成功");
}
信号:
HANDLE hdsm = CreateSemaphore(NULL, 0, 3, 'haihua'); //开辟一个信号,最大计数是3
HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, flash, 'haihua'); //打开信号
SEMAPHORE_ALL_ACCESS 全部
closeHandle(hdsm); //注销
实例:
DWORD WINAPI myworker(void *p)
{
int *pint = p;
HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, flash, 'eli');
if (myhsem)
{
if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)
{
//...
}
ReleaseSemaphore(myhsem, 1,NULL);//释放资源
CloseHandle(myhsem); //退出线程
}
}
void main()
{
HANDLE hSEM = CreateSemaphoree(NULL, 0, 3, 'eli');
int a[10] = {0,1,2,3,4,5,6,7,8,9};
HANDLE hd[10] = {0};
int i;
for (i = 0; i < 10; i++)
{
hd[i] = CreateThread(NULL, 0, myworker, a+i, 0, NULL);
}
sleep(2000);
printf("激活线程");
ReleaseSemaphore(hSEM,3,NULL);//激活
WaitForMultipleObject(10, hd, true, INFINITE);
closeHandle(hSEM);
}
互斥锁:
SRWLOCK g_lock;
第一个 InitializeSRWLock
函数功能:初始化读写锁
函数原型:VOID InitializeSRWLock(PSRWLOCK SRWLock);
函数说明:初始化(没有删除或销毁SRWLOCK的函数,系统会自动清理)
第二个 AcquireSRWLockExclusive
函数功能:写入者线程申请写资源。
函数原型:VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);
第三个 ReleaseSRWLockExclusive
函数功能:写入者线程写资源完毕,释放对资源的占用。
函数原型:VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
第四个 AcquireSRWLockShared
函数功能:读取者线程申请读资源。
函数原型:VOID AcquireSRWLockShared(PSRWLOCK SRWLock);
第五个 ReleaseSRWLockShared
函数功能:读取者线程结束读取资源,释放对资源的占用。
函数原型:VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);
注意一个线程仅能锁定资源一次,不能多次锁定资源。
实例:
int num = 0;
SRWLOCK g_lock;
DWORD WINAPI myworker(void *p) //写
{
AcquireSRWLockExclusive(&num);
while(++i != 101)
{
num++;
}
ReleaseSRWLockExclusive(&num);
}
DWORD WINAPI read(void *p) //读写
{
AcquireSRWLockShared(&num);
while(++i != 101)
{
num++;
}
ReleaseSRWLockShared(&num);
}
void main()
{
InitializeSRWLock(&num);
HANDLE hd[10] = {0};
CreateThread(NULL, 0, read, NULL, 0, NULL);
int i;
for (i = 0; i < 10; i++)
{
hd[i] = CreateThread(NULL, 0, myworker, NULL, 0, NULL);
}
WaitForMultipleObject(10, hd, true, INFINITE);
closeHandle(hSEM);
}
互斥量:为协调共同对一个共享资源的单独访问而设计的。
信号量:为控制一个具有有限数量用户资源而设计。
事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
临界区:
临界区最大线程是64.
一般情况下,使用多线程都会使用CPP,因为CPP中有临界区结构.
同时操作单一元素很容易产生冲突,这种时候就需要定义临界区.
*临界区不是一个变量,而是调用操作系统,锁定当前变量.
使用临界区需要使用CreateThread来创建线程.
定义临界区:
CRITICAL_SECTION cs;//临界区
原型:
struct CRITICAL_SECTION
{
LONG lockCount;
LONG RecursionCount;
HANDLE OwningThread;
HANDLE LockSemaphore;
ULONG_PTR SpinCount;
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
InitializeCriticalSection(&cs); //初始化
EnterCriticalSection(&cs); //进入临界区
//... 变量操作内容
LeaveCriticalSection(&cs);//离开临界区
DeleteCriticalSection(&cs); //删除临界区
事件:
createEvent(); //创建事件
HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa, //安全描述符,瞧,这是个内核对象
BOOL fManualReset,
BOOL fInitialState,
PCTSTR pszName);
fManualReset参数为TRUE时,表示创建一个人工重置的时间,为FALSE时表示创建一个自动重置事件。
fInitialState参数为TRUE时,指明该事件是要初始化为已通知状态,反之为未通知状态。
pszName 时间名称
OpenEvent(EVENT_ALL_ACCSEE,true,name); //打开事件
HANDLE OpenEvent(
DWORD fdwAccess,
BOOL fInherit,
PCTSTR pszName);
pszName 时间名称
SetEvent(); //设置信号启用
ResetEvent(); //复位信号
实例:
HANDLE event[3] = {0}; //事件
HANDLE hthread[3] = {0}; //线程
DWORD WINAPI firstthread(void *p)
{
SetEvent(event[0]);
return 0;
}
DWORD WINAPI secondthread(void *p)
{
WaitForSingleObject(event[0], INFINITE);// 等待信号
//...
ResetEvent(event[0]);
return 0;
}
void main()
{
//创建事件
event[0] = createEvent(NULL, TRUE, FLASH, NULL);
event[1] = createEvent(NULL, TRUE, FLASH, NULL);
hthread[0] = CreateThread(NULL, 0, firstthread, NULL, 0, NULL);
hthread[1] = CreateThread(NULL, 0, secondthread, NULL, 0, NULL);
WaitForMultipleObjects(2, hthread, true, INFINI);
printf("全部完成\n");
system("pause");
}
互斥量:
CreateMutex(); //创建互斥量
CreateMutex(NULL, FALSH, NULL);
参数1: 安全机制
参数2: 是否激活
ReleaseMutex(mutex); //注销互斥量
OpenMutex(MUTEX_ALL_ACCESS, TRUE, name); 打开互斥量
实例:
HANDLE mutex= NULL;
DWORD WINAPI add(void *p)
{
WaitForSingleObject(mutex, INFINITE);
int i = 0;
while(++i != 101)
{
num++;
}
ReleaseMutex(mutex);
}
void main()
{
mutex = CreateMutex(NULL, Flash, NULL);
HANDLE hd[64];
int i;
for (i = 0, i < 64; i++)
{
hd[i] = CreadThread(NULL, 0, add, NULL, 0, NULL);
}
WaitForMultipleObjects(64, hd, true, INFINITE);
for (i = 0, i < 64; i++)
{
CloseHandle(hd[i]);
}
system("pause");
}
原子操作:
原子操作可以理解为在寄存器中直接操作,速度快,可以避免多线程中的一些问题
原子操作的速度要快于互斥量,临界区,event
InterlockedIncrement(&num); //变量++操作
InterlockedExchangeAnd(&num, 1); //num++
InterlockedDecrement(&num); //num--
InterlockedExchange(); //改变
InterlockedAnd(&num, 1); // num + 1
时间同步:
单独定时器只能用在同步通信
SetWaitablesTimer(timer, &time, 0, NULL, 0 NULL)
参数3: 多少毫秒一次
参数4: 回调函数
参数5: 参数
回调函数声明格式:
//参数2与参数3是时差
void CALLBACK timerun(viod *parg, DWORD timeaeg, DWORD timehigh)
{
}
CamcelWaitableTimer(timer);//取消定时器
定时器:
//创建定时器
HANDLE timer = CreateWaitableTimer(NULL, TRUE, 'name');
if (timer == NULL)
return 0;
LARGE_INTEGER time; //可精确到小数点后7位
time.Quadpart = -2000000 // 2秒
SetWaitablesTimer(timer, &time, 0, NULL, 0 NULL);//设置定时器等待
if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0)
{
print("等待成功");
}
信号:
HANDLE hdsm = CreateSemaphore(NULL, 0, 3, 'haihua'); //开辟一个信号,最大计数是3
HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, flash, 'haihua'); //打开信号
SEMAPHORE_ALL_ACCESS 全部
closeHandle(hdsm); //注销
实例:
DWORD WINAPI myworker(void *p)
{
int *pint = p;
HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, flash, 'eli');
if (myhsem)
{
if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)
{
//...
}
ReleaseSemaphore(myhsem, 1,NULL);//释放资源
CloseHandle(myhsem); //退出线程
}
}
void main()
{
HANDLE hSEM = CreateSemaphoree(NULL, 0, 3, 'eli');
int a[10] = {0,1,2,3,4,5,6,7,8,9};
HANDLE hd[10] = {0};
int i;
for (i = 0; i < 10; i++)
{
hd[i] = CreateThread(NULL, 0, myworker, a+i, 0, NULL);
}
sleep(2000);
printf("激活线程");
ReleaseSemaphore(hSEM,3,NULL);//激活
WaitForMultipleObject(10, hd, true, INFINITE);
closeHandle(hSEM);
}
互斥锁:
SRWLOCK g_lock;
第一个 InitializeSRWLock
函数功能:初始化读写锁
函数原型:VOID InitializeSRWLock(PSRWLOCK SRWLock);
函数说明:初始化(没有删除或销毁SRWLOCK的函数,系统会自动清理)
第二个 AcquireSRWLockExclusive
函数功能:写入者线程申请写资源。
函数原型:VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);
第三个 ReleaseSRWLockExclusive
函数功能:写入者线程写资源完毕,释放对资源的占用。
函数原型:VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
第四个 AcquireSRWLockShared
函数功能:读取者线程申请读资源。
函数原型:VOID AcquireSRWLockShared(PSRWLOCK SRWLock);
第五个 ReleaseSRWLockShared
函数功能:读取者线程结束读取资源,释放对资源的占用。
函数原型:VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);
注意一个线程仅能锁定资源一次,不能多次锁定资源。
实例:
int num = 0;
SRWLOCK g_lock;
DWORD WINAPI myworker(void *p) //写
{
AcquireSRWLockExclusive(&num);
while(++i != 101)
{
num++;
}
ReleaseSRWLockExclusive(&num);
}
DWORD WINAPI read(void *p) //读写
{
AcquireSRWLockShared(&num);
while(++i != 101)
{
num++;
}
ReleaseSRWLockShared(&num);
}
void main()
{
InitializeSRWLock(&num);
HANDLE hd[10] = {0};
CreateThread(NULL, 0, read, NULL, 0, NULL);
int i;
for (i = 0; i < 10; i++)
{
hd[i] = CreateThread(NULL, 0, myworker, NULL, 0, NULL);
}
WaitForMultipleObject(10, hd, true, INFINITE);
closeHandle(hSEM);
}