多线程基础之三:使用event, mutex, semaphore实现多进程间互斥

news/2024/5/18 7:14:46 标签: 多线程, semaphore, mutex, event

前面文章介绍了使用mutexsemaphore多线程场景中实现线程互斥。事实上,因为mutex, semaphore是内核对象,虽然是在某一个进程中创建的,但是由于进程间可以共享内核模块,故而使用mutex, semaphore在进程间作为互斥标识量也是可以的。


0. 使用mutex实现多进程间互斥

race_process_mutex_1.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[50] = "multiple_process_shared_mutex_test";
void main()
{ 
    HANDLE g_Mutex = CreateMutexA(NULL, TRUE, name); //如何句柄创建成功,则返回有效的句柄值

    if(g_Mutex)
        printf("句柄创建成功\n");
    else
    {
        printf("句柄创建失败\n");
        return;
    }
    char ch = getchar();
    ReleaseMutex(g_Mutex);//离开互斥区
    printf("宿主进程已经释放了互斥量,其余进程可以触发互斥量\n");
    CloseHandle(g_Mutex);
}

race_process_mutex_2.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[50] = "multiple_process_shared_mutex_test";

void main()
{

    HANDLE mutex = OpenMutexA(MUTEX_ALL_ACCESS,TRUE,name);//MUTEX_ALL_ACCESS查找全部
    if (mutex==NULL)
    {
        printf("给定参数名称的mutex内核对象打开失败,可能尚未创建该mutex\n");
        system("pause");
        return;
    }
    printf("----已搜索到指定的mutex内核对象,正在等待获取使用该对象-----\n");
    DWORD res = WaitForSingleObject(mutex, 20000);
    switch (res)
    {
    case WAIT_OBJECT_0:
        printf("----收到信号,成功获取到该mutex,下面本进程可以进入critical section进行操作-----\n");
        break;
    case WAIT_TIMEOUT:
        printf("----超时,mutex宿主进程依旧在声明使用该mutex中-----\n");
        break;
    case WAIT_ABANDONED:
        printf("----mutex宿主进程意外终止-------\n");
        break;
    default:
        break;

    }
    CloseHandle(mutex);
    system("pause");
}


1. 使用semaphore实现多进程间互斥

race_process_semaphore_1.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[50] = "multiple_process_shared_mutex_test";

void main()
{
    HANDLE hsem = CreateSemaphoreA(NULL, 0, 1, name);
    //第二各参数为0,代表进程创建信号量之时便声明了对该信号量的占用
    printf("宿主进程创建信号量成功");
    char ch = getchar();

    ReleaseSemaphore(hsem, 1, NULL);
    printf("宿主进程已释放对信号量的使用,其余进程可触发信号量");
    CloseHandle(hsem);
}

race_process_semaphore_2.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[50] = "multiple_process_shared_mutex_test";
void main()
{
    HANDLE hsem = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, TRUE, name);
    if (hsem == NULL)
    {
        printf("给定参数名称的semaphore内核对象打开失败,可能尚未创建该semaphore\n");
        system("pause");
        return;
    }
    printf("----已搜索到指定的semaphore内核对象,正在等待获取使用该对象-----\n");
    DWORD res = WaitForSingleObject(hsem, 20000); //第二个参数20000,单位ms,代表最多监听该信号量20s
    switch (res)
    {
    case WAIT_OBJECT_0:
        printf("----收到信号,成功获取到该semaphore,下面本进程可以进入critical section进行操作-----\n");
        break;
    case WAIT_TIMEOUT:
        printf("----超时,semaphore宿主进程依旧在声明使用该semaphore中-----\n");
        break;
    /*semaphoreevent类似,并不能检测到宿主进程的主动中断,故而只能等待时间耗光后才会响应,故而这也是semaphore相比于Mutex的缺点。即semaphore的宿主进程主动终止了,该监听进程也只能被动地耗光所有的等待时间,而不能监听到对方进程终止了。
    case WAIT_ABANDONED:
        printf("----semaphore宿主进程意外终止-------");
        break;
    */
    default:
        break;
    }
    CloseHandle(hsem);
    system("pause");
}


2. 使用event实现多进程间协同执行

race_process_event_1.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

char name[50] = "multiple_process_shared_mutex_test";
void main()
{
    HANDLE event = CreateEventA(NULL, FALSE, FALSE, name);
    printf("宿主进程创建信号量成功");
    char ch = getchar();

    SetEvent(event);
    printf("宿主进程激活了event,等待其他进程触发event");
    CloseHandle(event);

    system("pause");
}

race_process_event_2.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>


char name[50] = "multiple_process_shared_mutex_test";

void main()
{
    HANDLE event = OpenEventA(EVENT_ALL_ACCESS, TRUE, name);//打开事件

    if (event == NULL)
    {
        printf("给定参数名称的event内核对象打开失败,可能尚未创建该event\n");
        system("pause");
        return;
    }
    printf("----已搜索到指定的event内核对象,正在等待获取使用该对象-----\n");
    DWORD res = WaitForSingleObject(event, 20000);
    switch (res)
    {
     case WAIT_OBJECT_0:
        printf("----收到信号,成功激活目标event,下面本进程可以进行后续的协同操作-----\n");
        break;
    case WAIT_TIMEOUT:
        printf("----超时,目标event的宿主进程依旧未激活该event该其他进程使用----\n");
        break;
    /*
    //event机制其实是感知不到宿主进程中断丢失的情况,这也是event相比于Mutex最大的缺点
    case WAIT_ABANDONED:
        printf("-------目标event的宿主进程意外终止-------");
        break;
    */
    default:
        break;

    }
    CloseHandle(event);
    system("pause");
}

根据上面可以看到基本上内核对象都是可以改装使用在多进程间用于信息交换的,这是多进程间进行信号(开或关)的交互方式,而多进程间更大规模的数据交互则涉及到其他的机制,如进程间Message(Windows socket套接字便属于这类),共享内存块、管道pipeline等技术。

总结本文的内容,简单的一句话,如果单纯只是开关锁,在两个进程中实现互斥,mutexevent和semaphre更安全,响应性更好。


http://www.niftyadmin.cn/n/1030875.html

相关文章

多线程基础之四:Linux提供的原子锁类型atomic_t

在x86体系下&#xff0c;任何处理器平台下都会有一些原子性操作&#xff0c;在单处理器情况下&#xff0c;单步指令的原子性容易实现。但是在SMP多处理器情况下&#xff0c;只有那些单字的读&#xff08;将变量读进寄存器&#xff09;或写&#xff08;从寄存器写入到变量地址&a…

Packages目录下Shader打包疑问

1&#xff09;Packages目录下Shader打包疑问 ​2&#xff09;如何关闭资源的RW选项 3&#xff09;RenderTexture单个像素的色值大于Shader的输出值 4&#xff09;客户端背包刷新机制 5&#xff09;PBXProject.AddCapability添加失败 这是第218篇UWA技术知识分享的推送。今天我们…

多线程基础之五:Windows API提供的mutex和semaphore性能比较

Windows系统提供HANDLE WINAPI CreateSemaphore(xxx)和HANDLE WINAPI CreateMutex(xxx)直接提供Mutex和Semaphore两种内核对象供程序员使用在临界区互斥操作。在前面的多线程基础之一提到过Semaphore存在Binary和Counting两种&#xff0c;其中Binary Semaphore等同于Mutex&…

多线程基础之六:Pthread Win32实现的非阻塞请求机制的Semaphore

前面看到Windows API直接提供的Semaphore并没有为其配备等待队列&#xff0c;从而无法实现非阻塞请求机制以实现操作加速&#xff0c;对于临界区耗时的情况下&#xff0c;显然是存在实现非阻塞请求机制的Semaphore的。Linux下的Pthread库实现了这样的增加版Semaphore&#xff0…

UWA DAY 2020 课程视频已上线

“品往鉴来&#xff0c;质存高远” UWA DAY 2020已落下帷幕&#xff0c;UWA再次以丰富多样的专题内容、具有前瞻性的技术洞见呈现于众。再次感谢您对本次大会的关注与支持&#xff0c;希望对您而言这是一段美好的回忆。UWA DAY 2020的大部分议题已发布于UWA学堂&#xff0c;欢迎…

多线程基础之七:多线程遇上printf的“延迟写”策略

0. 运行库提供的IO读写函数采用“延迟写”策略的原因编程时经常会用到printf()函数&#xff0c;但是由于printf()函数涉及到和显示器或磁盘等外设进行交互&#xff0c;所以操作涉及到从“用户态–>内核态–>返回用户态”的一系列内核转换过程&#xff0c;但是从用户态通过…

MMORPG手游合理的性能参数

1&#xff09;MMORPG手游合理的性能参数 ​2&#xff09;使用ScriptableBuildPipeline打包的疑问 3&#xff09;如何获取到Animation修改材质球颜色后的颜色值 4&#xff09;嵌套预设AssetBundle打包的疑问 5&#xff09;LWRP渲染下&#xff0c;Profiler中函数开销高 这是第219…

缓冲技术之二:缓冲池BufferPool的简单实现

在文章缓冲技术中提到无论是单缓冲、双缓冲或循环缓冲&#xff0c;均仅是进程专属缓冲配备&#xff0c;而一旦考虑到操作系统的分时并行特性&#xff0c;任一时刻只有一个进程的缓冲体系在工作之中&#xff0c;而其他进程的缓冲体系并不在工作&#xff08;要么是迁移到swap cac…