操作系统-线程同步

本文探讨了线程同步在多线程并发中的关键概念,如原子访问、临界区、互斥量、事件和信号量的使用,以确保数据一致性并避免竞态条件。通过实例演示了如何通过Windows API实现线程间的协作,强调了内核对象在跨进程同步中的优势和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 *   线程同步解决多线程并发的问题
 *      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();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值