/*
* 线程同步解决多线程并发的问题
* 1.原子访问:同一时刻只允许一个线程访问资源(变量)
* volitale 防止编译优化,直接操作内存
* 2.临界区(关键段):同一时刻只允许一个线程访问代码段
* 用法:定义并在创建线程之初始化,进入代码区,离开代码区。
* 作用:消除重复,但是出现负值
* 出现负值的原因:票数已经卖完了,还要--
* 1号线程操作完后,12345等其他线程会一起抢着进入代码区,出现惊群效应。
* 实现方式:
* 1) 直接阻塞 2) 旋转锁 (等一会儿再阻塞) InitializeCriticalSectionAndSpinCount(&g_cs,5);
* 3) 非阻塞 TryEnterCriticalSection(&g_cs); 不阻塞直接去找其他的
* 内核对象: 3.互斥量 同一时刻只允许一个线程访问代码段 拥有初始拥有权
* 4.事件 同一时刻只允许一个线程访问代码段 人工/自动
* CreateEventW
* if (WAIT_TIMEOUT==WaitForSingleObject(m_hEevnt,10))
* SetEvent(m_hEevnt);
* 5.信号量 同一时刻只允许一个线程访问代码段 指定个数
* CreateSemaphoreW
* if (WAIT_TIMEOUT==WaitForSingleObject(m_hSemapore,10))
* ReleaseSemaphore(m_hSemapore,1,0);
* 内核对象与临界区相同点:
* 同一时刻只允许一个线程访问代码段
* 内核对象与临界区不同点:
* 适用范围:内核对象支持跨进程
* 灵活性、安全性:内核对象即安全又灵活 (临界区里面的服务被kill,不会被释放。内核对象互斥锁会自动释放)
* 效率性:临界区效率更高,用户模式下的线程同步 互斥量:在内核模式下的线程同步
*/
#include <QCoreApplication>
/*A-B 有100张车票 10 售完为止*/
#include <windows.h>
#include <stdio.h>
#define MAXNUM 10
int g_Ticket = 100;
HANDLE g_aryThread[MAXNUM];
HANDLE M_hMutex = CreateMutexW(
0,//安全属性
0,//初始拥有者
0 //名字
);
HANDLE m_hEevnt = CreateEventW(NULL,FALSE,TRUE,0);//安全属性、人工/自动、信号、名字
HANDLE m_hSemapore = CreateSemaphoreW(
0,//安全属性
1,//初始化的数量
1,//最大值
0 //名字
);
CRITICAL_SECTION g_cs;
DWORD WINAPI ThreadProc(LPVOID lpParameter)//线程原型
{
while(1)
{
if (g_Ticket<=0)
break;
//2.临界区
//EnterCriticafile:///D:/document-cao/工作/C++/阿秀面试整理.pdflSection(&g_cs); //直接阻塞
//3.互斥锁
//WaitForSingleObject(M_hMutex,INFINITE); //不会出现惊群效应
//4.事件
// if (WAIT_TIMEOUT==WaitForSingleObject(m_hEevnt,10))
// continue;
//5.信号量
if (WAIT_TIMEOUT==WaitForSingleObject(m_hSemapore,10))
continue;
//解决负数问题
if (g_Ticket<=0){
//ReleaseMutex(M_hMutex);
//LeaveCriticalSection(&g_cs);
}
printf("current thread is [%d] the ticket number is: %d \n",GetCurrentThreadId(),g_Ticket);
g_Ticket--;
ReleaseSemaphore(m_hSemapore,1,0);
//SetEvent(m_hEevnt);
//ReleaseMutex(M_hMutex);
//LeaveCriticalSection(&g_cs);
//1.原子访问
//InterlockedDecrement((LONG *)&g_Ticket);
Sleep(10);//让出时间片
}
return 0;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//初始化
//旋转锁
//InitializeCriticalSectionAndSpinCount(&g_cs,5);
//2.临界区
//InitializeCriticalSection(&g_cs);
//创建10个线程
for(int i = 0; i < MAXNUM; i++)
{
g_aryThread[i] = CreateThread(0,0,&ThreadProc,0,0,0);
}
return a.exec();
}
本文探讨了线程同步在多线程并发中的关键概念,如原子访问、临界区、互斥量、事件和信号量的使用,以确保数据一致性并避免竞态条件。通过实例演示了如何通过Windows API实现线程间的协作,强调了内核对象在跨进程同步中的优势和效率。

被折叠的 条评论
为什么被折叠?



