当前位置: 首页 > news >正文

多线程同步-条件变量

1.简介

当想入写入者线程和读取者线程以独占模式或共享模式访问同一个资源的时候,可以使用SRWLOCK读写锁。

  • 如果读取者线程没有数据可读取,那么它应该将锁释放并等待,直到写入者线程产生了新的数据为止。
  • 如果写入者线程产生的数据写满,那么写入者线程同样应该释放SRWLOCK并进入睡眠状态,直到读取者线程把数据清空为止。

windows通过SleepConditionVariableCS或SleepConditionVariableSRW函数,提供了一种条件变量。

BOOL SleepConditionVariableCS(
  [in, out] PCONDITION_VARIABLE ConditionVariable,
  [in, out] PCRITICAL_SECTION   CriticalSection,
  [in]      DWORD               dwMilliseconds
);
BOOL SleepConditionVariableSRW(
  [in, out] PCONDITION_VARIABLE ConditionVariable,
  [in, out] PSRWLOCK            SRWLock,
  [in]      DWORD               dwMilliseconds,
  [in]      ULONG               Flags
);
  • ConditionVariable:指向一个已初始化的条件变量。
  • 参数2:指向一个关键段或者SRWLock指针。
  • dwMilliseconds:表示希望线程花多少时间来等待条件变量被触发。
  • Flags:指定一旦条件变量被触发,希望线程以何种方式来得到锁:对写入者线程来说,应该传入0,对读取者线程来说,传入CONDITION_VARIABLE_LOCKMODE_SHARED。

当指定的时间用完时候,如果条件变量未被触发,返回FALSE,否则返回TRUE。

当另一个线程检测到相应的条件已经满足的时候,比如有数据可读取了,它会调用下面的函数,阻塞在Sleep*函数中的线程会被唤醒。

    WakeAllConditionVariable();
    WakeConditionVariable();

2.示例

创建两个等待线程,一个苏醒线程,等待几秒后,sets线程,唤醒所有的别的线程。别的线程唤醒后执行结束退出。

// Interlocked.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <windows.h>

DWORD WINAPI sets(LPVOID);
DWORD WINAPI write(LPVOID);


BOOL RUNNING = FALSE;
SRWLOCK  g_srwlock;         //读写同步对象  
CONDITION_VARIABLE g_con;  //条件变量

int main()
{
    HANDLE aThread[3];
    DWORD ThreadID;

    InitializeConditionVariable(&g_con);
    InitializeSRWLock(&g_srwlock);

    //创建多线程
    aThread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)write, NULL, 0, &ThreadID);
    if (aThread[0] == NULL)
    {
        printf("CreateThread error: %d\n", GetLastError());
        return 1;
    }

    aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)write, NULL, 0, &ThreadID);
    if (aThread[0] == NULL)
    {
        printf("CreateThread error: %d\n", GetLastError());
        return 1;
    }

    aThread[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sets, NULL, 0, &ThreadID);
    if (aThread[0] == NULL)
    {
        printf("CreateThread error: %d\n", GetLastError());
        return 1;
    }


    WaitForMultipleObjects(3, aThread, TRUE, INFINITE);

    // Close thread and mutex handles

    for (int i = 0; i < 3; i++)
        CloseHandle(aThread[i]);

    return 0;

}

DWORD WINAPI write(LPVOID lpParam)
{
    UNREFERENCED_PARAMETER(lpParam);

    AcquireSRWLockExclusive(&g_srwlock);

    if (RUNNING == FALSE)
        SleepConditionVariableSRW(&g_con, &g_srwlock, INFINITE, 0);


    printf("write Thread %d finished...\n",
        GetCurrentThreadId());

    ReleaseSRWLockExclusive(&g_srwlock);

    return 1;
}

DWORD WINAPI sets(LPVOID lpParam)
{
    UNREFERENCED_PARAMETER(lpParam);

    AcquireSRWLockExclusive(&g_srwlock);

    for (int i = 0; i < 100; ++i)
    {
        Sleep(50);
        printf("sets Thread %d wait...\n", GetCurrentThreadId());
    }

   
    ReleaseSRWLockExclusive(&g_srwlock);
    WakeAllConditionVariable(&g_con);

    return 1;
}

 执行结果:

 

相关文章:

  • FPGA项目开发之同步信号和亚稳态
  • 【机器学习】Linear Regression Experiment 线性回归实验 + Python代码实现
  • 【数据结构 C语言版】第四篇 栈、堆栈、Stack(超级详细版)
  • Django(3):数据模型定义
  • Linux系统编程·进程概念引入
  • 对抗生成网络GAN系列——CycleGAN简介及图片春冬变换案例
  • 第二课 ceph基础学习-OSD扩容换盘和集群运维
  • 帮助命令---学习Linux命令的第一步
  • C++ - 文件读写(fstream)
  • JavaScript:二维码生成与解析
  • SpringBoot 2 配置文件 2.4 多环境配置
  • JavaWeb编年史(远古时期)
  • 【Spring】面向切面编程详解(AOP)
  • 第四课 ceph基础学习-RGW高可用集群和集群测试
  • 幼儿园小程序实战开发教程
  • [笔记] php常见简单功能及函数
  • Android组件 - 收藏集 - 掘金
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • dva中组件的懒加载
  • gcc介绍及安装
  • js
  • leetcode46 Permutation 排列组合
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • MySQL几个简单SQL的优化
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • quasar-framework cnodejs社区
  • Spring Boot快速入门(一):Hello Spring Boot
  • springMvc学习笔记(2)
  • WebSocket使用
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 动态魔术使用DBMS_SQL
  • 复杂数据处理
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 技术发展面试
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 如何解决微信端直接跳WAP端
  • 如何胜任知名企业的商业数据分析师?
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​ssh免密码登录设置及问题总结
  • ​第20课 在Android Native开发中加入新的C++类
  • (11)MSP430F5529 定时器B
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (SpringBoot)第七章:SpringBoot日志文件
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)用.Net的File控件上传文件的解决方案
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET 依赖注入和配置系统
  • .NET开源快速、强大、免费的电子表格组件
  • /proc/stat文件详解(翻译)