[笔记]线程执行和资源存取

本文详细介绍了Windows系统下的线程同步机制,包括全局变量、事件、临界区、互斥量、信号量等同步手段,并通过示例代码展示了如何使用这些机制来确保线程之间的正确同步。

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

  线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应该一直等待,直到消息到达时才被唤醒.
  线程互斥是指对于共享资源,在各线程访问时的排它性。即当有多个线程都要使用某一共享资源时,同一时刻却只允许一个线程去使用,而其他要使用的该共享资源的线程必须等待,直到占用资源者释放该共享资源。
  实际上线程互斥是一种特殊的线程同步。
  在Win32中,同步机制主要有以下几种:

一、全局变量

int var ;  //全局变量
UINT ThreadFunction(LPVOID pParam)
{
    while(var)
    {
        //线程处理
    }
    return 0 ;
}

二、事件

  1.创建事件

HANDLE CreateEvent(
  PSECURITY_ATTRIBUTES psa,
  BOOL bManualReset,
  BOOL bInitialState,
  PCTSTR pszName);
  • 第一个参数与CreateThread中的第一个参数类似,是一个指向SECURITY_ATTRIBUTES结构的指针;
    第二个参数bManualReset告诉系统创建manual-reset(TRUE)还是auto-reset(FALSE)类型的对象;(当manual-reset事件状态变为signaled时,所有等待该事件的线程都成为可调度的,当auto-reset事件状态变为signaled时,等待该事件的所有线程中只会有一个成为可调度的。)
    第三个参数bInitialState用来指明事件对象的状态初始化为signaled(TRUE)或unsignaled(FALSE);
    第四个参数为事件的名称。
    2.打开和关闭事件
    HANDLE hEvent = OpentEvent(EVETN_ALL_ACCESS, true, “MyEvent”) ;
    CloseHandle(hEvent) ;
    3.状态控制
    函数SetEvent将事件对象置为signaled状态:
        BOOL SetEvent(HANDLE hEvent)
    函数ResetEvent将事件对象重置为unsignaled:
        BOOL ResetEvent(HANDLE hEvent)
  • 微软为auto-reset类型的事件对象定义了“成功等待的副作用”——当某线程等待该对象成功时,对象状态会自动重置为unsignaled,因此通常没有必要为auto-reset类型的对象调用ResetEvent。要注意,微软并未为manual-reset类型的事件对象定义这种机制。
    4.等待控制
    WaitForSingleObject(evRead, INFINITE) ;
    5.实例


三、临界区

  临界区适用于多个线程之间没有先后顺序但要求互斥的同步。多个线程访问同一个临界区的原则:
  (1)一次最多只能一个线程停留在临界区内;
  (2)不能让一个线程无限地停留在临界区内,否则其他线程将不能进入临界区。
  定义临界区变量的方法如下:
    CRITICAL_SECTION gCriticalsection ;
  初始化临界区:
    VOID WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) ;
  删除临界区:
    VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) ;
  进入临界区:
    VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) ;
  离开临界区:
    VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) ;

四、互斥量

  CreateMutex:创建一个互斥对象,返回对象句柄;
  OpenMutex:打开并返回一个已经存在的互斥对象的句柄,使之后续访问;
  WaitForSingleObject(hMutex, INFINITE) :等待互斥量;
  ReleaseMutex:释放互斥对象占用,使之成为可用。

五、信号量

  信号量是一个核心对象,拥有一个计数器,可以用来管理大量有限的系统资源。当计数器大于零时,信号量为有信号状态;当计数器为零时,信号量处于无信号状态。
  创建信号量:
   HANDLE CreateSemaphore( PSECURITY_ATTRIBUTE  psa,
                  LONG lInitialCount,
                  LONG lMaximumCount,
                  PCTSTR psaName) ;
  释放信号量:
   BOOL WINAPI ReleaseSemaphoe(HANDLE hSemaphore,
                  LONG lReleaseCount,
                  LPLONG lpPreviousCount) ;
  打开信号量:
    HANDLE OpenSemaphore( DWORD fdwAccess,
                  BOOL bInherithandle,
                  PCTSTR pszName) ;

六、模板

#include <windows.h>
#include <iostream.h>
 
#define THREAD_INSTANCE_NUMBER 3
 
LONG g_fResourceInUse = FALSE ;
LONG g_lCounter = 0 ;
 
DWORD ThreadProc(void *pData)
{
    int ThreadNumberTemp = (*(int*)pData) ;
 
    HANDLE hMutex ;
    //1.打开互斥量
    if((hMutex=OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Mutex.Test"))==NULL)
    {
        cout<<"Open Mutex error!"<<endl ;
        return 1 ;
    }
    //2.等待互斥
    WaitForSingleObject(hMutex, INFINITE) ;
    
    //3.用户代码**********
    
    //4.释放互斥量
    ReleaseMutex(hMutex) ;
    //5.关闭句柄
    CloseHandle(hMutex) ;
    return 0 ;
}
 
int main(int argc, char *argv[])
{
    int i; 
    DWORD ID[THREAD_INSTANCE_NUMBER];
    HANDLE h[THREAD_INSTANCE_NUMBER];
    HANDLE hMutex ;
 
    //创建互斥量
    if((hMutex=OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Mutex.Test"))==NULL)
        if((hMutex=CreateMutex(NULL,FALSE, "Mutex.Test"))==NULL)
        {
            cout<<"Create Mutex error!"<<endl ;
            return 0 ;
        }
    for(i=0; i<THREAD_INSTANCE_NUMBER ;i++)
    {
        h[i] = CreateThread(NULL,
                            0,
                            (LPTHREAD_START_ROUTINE) ThreadProc,
                            (void *) &ID[i],
                            0,
                            &(ID[i])) ;
        if(h[i]==NULL)
            cout<<"CreateThread error"<<ID[i]<<endl ;
        else
            cout<<"CreateThread :"<<ID[i]<<endl ;
    }
    WaitForMultipleObjects(THREAD_INSTANCE_NUMBER, h, TRUE, INFINITE) ;
    cout<<"Close the Mutex Handle!"<<endl; 
    CloseHandle(hMutex) ;
 
    return 0 ;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值