+ -

Windows平台进程间通信: 互斥体,同步段,信号量

时间:2010-09-02

来源:kgisme170

在手机上看
手机扫描阅读
        Mutex是一种全局对象,常用于线程和进程的同步。一个Mutex就是一把锁,同时只能一个对象拥有。当然,如果只是为了保证一段代码可重入,创建一个互斥访问去的话,用CriticalSection比Mutex快的多。当然,CriticalSection只能是线程间通信。如果要求再次加锁的时候阻塞,就要用Semaphore。WaitForSingleObject是等待特定对象发出信号(signaled),而Mutex对象在没有任何线程持有时会发出信号。下面这个程序中,用Mutex保证程序只运行一个实例。如果程序运行不超过3个实例呢? 用信号量就可以了。
        如果不指定名字,那么Mutex和Semaphore就是匿名的,只能进程内使用了。
1. Mutex的例子: 这个程序保证只有一个实例运行。

#include"stdafx.h"
#include<windows.h>
#include<winbase.h>
#include<stdio.h>
CRITICAL_SECTION cs;
int count=0;
UINT WINAPI mythread(void* p){//可重入的函数
  EnterCriticalSection(&cs);
  printf("thread id =%d, count=%d\n",(DWORD*)p,++count);
  LeaveCriticalSection(&cs);
  return 0;
}
int main(void){
    InitializeCriticalSection(&cs);//不能漏掉这句
    HANDLE hMutex=CreateMutex(NULL,FALSE,"mymutex");
    if(!hMutex || INVALID_HANDLE_VALUE==hMutex){return 1;}
    DWORD dw=WaitForSingleObject(hMutex,0);
    if(WAIT_FAILED==dw){
        CloseHandle(hMutex);
        return 2;
    }else if(WAIT_TIMEOUT==dw){//another instance

        CloseHandle(hMutex);
        return 3;
    }else if(WAIT_ABANDONED==dw){
        printf("another instance ended just now\n");
    }
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
    DWORD id;
    HANDLE hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mythread,(LPVOID)GetCurrentThreadId(),0,&id);
    WaitForSingleObject(hThread,1000);
    return 0;
}

       
注意到,Mutex通常用于线程之间的同步,必须在CreateMutex的时候指定属主,那么WaitForSingleObject就会等待属主线程调用ReleaseMutex释放互斥锁。就像下面这个例子:

/*
程序的执行结果是:

子线程等待
主线程释放
子线程释放
主线程等待:0
Press any key to continue . . .
-------------------------------------------------------------------
如果在CreateMutex的时候,bOwner指定为false那么hMutex就不属于主线程。
子线程的WaitForSingleObject可以立刻得到mutex而无需等待主线程Release。执行的结果就会变成

子线程等待
子线程释放
主线程释放
主线程等待:0
*/
#include<windows.h>
#include<windef.h>
#include<stdio.h>
#define BUFSIZE 1024
#define NAME "mymutex1"
HANDLE hMutex;
VOID* mythread(VOID* ){
    printf("子线程等待\n");
    WaitForSingleObject(hMutex,INFINITE);
    printf("子线程释放\n");
    ReleaseMutex(hMutex);
    return 0;
}
int main(void){
    hMutex=CreateMutex(NULL,TRUE,NAME);
    if(!hMutex || INVALID_HANDLE_VALUE==hMutex){
        printf("CreateMutex failed:%d\n",GetLastError());
        return 1;
    }
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mythread,0,0,0);
    Sleep(100);//使得子线程有时间先运行

    ReleaseMutex(hMutex);
    printf("主线程释放\n");
    BOOL ret=WaitForSingleObject(hMutex,INFINITE);
    printf("主线程等待:%d\n",ret);
    CloseHandle(hMutex);
    return 0;
}


2. 用Semaphore的例子: 信号量就是一个全局计数器。下面的程序保证自己运行不超过3个实例。

#include"stdafx.h"
#include<windows.h>
#include<winbase.h>
#include<stdio.h>
int main(void){
    HANDLE sm=CreateSemaphore(NULL,3,3,"mysm");
    if(!sm||INVALID_HANDLE_VALUE==sm)exit(1);
    BOOL ret=WaitForSingleObject(sm,INFINITE);
    if(WAIT_TIMEOUT==ret){
        printf("You're running 3 instances, no more!\n");
        return 2;
    }
    ReleaseSemaphore(sm,1,NULL);
    CloseHandle(sm);
    printf("OK\n");
    return 0;
}


CreateSemaphore创建的时候如果起始计数=0,那么WaitForSingleObject()作为V原语是会阻塞的。ReleaseSemaphore作为P原语是增加计数。下面的程序说明了Semaphore的计数工作方式:

#include<windows.h>
#include<windef.h>
#include<stdio.h>
#define BUFSIZE 1024
#define NAME "mysem"
HANDLE hSem;
VOID* mythread1(VOID* ){
    WaitForSingleObject(hSem,INFINITE);
    printf("子线程1得到\n");
    Sleep(3000);
    ReleaseSemaphore(hSem,1,NULL);
    return 0;
}
VOID* mythread2(VOID* ){
    WaitForSingleObject(hSem,INFINITE);
    printf("子线程2得到\n");
    Sleep(3000);
    ReleaseSemaphore(hSem,1,NULL);
    return 0;
}
int main(void){
    hSem=CreateSemaphore(NULL,1,1,NAME);
    if(INVALID_HANDLE_VALUE==hSem)exit(1);
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mythread1,0,0,0);
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mythread2,0,0,0);
    Sleep(1000);//使得子线程有时间先运行

    printf("主线程执行\n");
    ReleaseSemaphore(hSem,1,NULL);//使得另一个线程得到计数

    Sleep(10000);
    CloseHandle(hSem);
    return 0;
}

程序运行结果是:
子线程1得到
主线程执行
子线程2得到
Press any key to continue . . .

热门下载

更多