zoukankan      html  css  js  c++  java
  • 使用Win32 API实现生产者消费者线程同步

    使用win32 API创建线程,创建信号量用于线程的同步

    创建信号量

    语法例如以下

    HANDLE semophore;
    semophore =  CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName);

    CreateSemophore函数的原型例如以下:

    HANDLE WINAPI CreateSemaphore(
      _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,//属性
      _In_     LONG                  lInitialCount,//初始值
      _In_     LONG                  lMaximumCount,//最大值
      _In_opt_ LPCTSTR               lpName//信号量对象的名字
    );
    函数返回一个指向信号量对象的句柄,是一个HANDLE对象

    wait操作和signal操作

    使用结构通常是这种

    while(true){
    
        WaitForSingleObject(semophore,INFINITE);//wait操作
            //临界区
        ReleaseSemaphore(semophore,1,NULL);//signal操作
    }

    两个函数的原型例如以下:

    DWORD WaitForSingleObject(
      HANDLE hHandle,//句柄。能够指向信号量或者线程
      DWORD dwMilliseconds//等待的毫秒数
    );
    BOOL ReleaseSemaphore(
      HANDLE hSemaphore,//句柄,指向信号量
      LONG lReleaseCount,//给信号量添加值,通常是1
      LPLONG lpPreviousCount//保存信号量之前的值的变量的指针
    );

    创建线程

    HANDLE producer;
    //PRODUCER 线程运行这个函数
    //pro_id 线程id
    producer = CreateThread(NULL, 0, PRODUCER, NULL, 0, &pro_id);//创建线程

    函数原型

    HANDLE WINAPI CreateThread(
      _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,//指向线程属性结构体的指针
      _In_      SIZE_T                 dwStackSize,//栈的初始化大小,0表示使用默认的大小
      _In_      LPTHREAD_START_ROUTINE lpStartAddress,//起始地址,也就是线程函数的指针
      _In_opt_  LPVOID                 lpParameter,//线程函数參数的指针
      _In_      DWORD                  dwCreationFlags,//控制创建的标志位,0表示线程创建后马上运行,CREATE_SUSPENDED表示新建为suspended状态,直到 ResumeThread 被调用时才运行。STACK_SIZE_PARAM_IS_A_RESERVATION,由dwStackSize 參数指定初始的保留栈的大小。不指定的话,dwStackSize指定提交的大小
      _Out_opt_ LPDWORD                lpThreadId//线程id的指针
    );


    生产者消费者线程同步代码例如以下

    #include<Windows.h>
    #include<iostream>
    
    #define QUEUE_LENGTH 10  //缓冲区长度
    
    HANDLE full_sem;		//满信号量
    HANDLE empty_sem;		//空信号量
    
    struct Msg
    {
    	int i;
    };//消息结构
    
    Msg MsgQueue[QUEUE_LENGTH]; //缓冲区
    int head = 0;//队列头
    int tail = 0;//队列尾
    
    DWORD WINAPI CONSUMER(LPVOID lpParameter){//消费者线程
    	for (int i = 0;;i++){
    		
    		WaitForSingleObject(full_sem, INFINITE);//wait操作
    		//WaitForSingleObject(mutex, INFINITE);//多个消费者须要加相互排斥信号量
    		int val = MsgQueue[head].i;
    		head = (head + 1) % QUEUE_LENGTH;
    		//ReleaseSemaphore(mutex, 1, NULL);//signal操作
    		std::cout << "CONSUMER : "<<val<< std::endl;
    		
    		ReleaseSemaphore(empty_sem, 1, NULL);//signal操作
    	}
    	
    	return 0;
    }
    
    DWORD WINAPI PRODUCER(LPVOID lpParameter){//生产者线程
    	for (int i = 0;; i++){
    		WaitForSingleObject(empty_sem, INFINITE);
    		//WaitForSingleObject(mutex, INFINITE);//多个生产者须要加相互排斥信号量
    		MsgQueue[tail].i = i;
    		tail=(tail+1) % QUEUE_LENGTH;
    		//ReleaseSemaphore(mutex, 1, NULL);
    		std::cout << "PRODUCER : " <<i<< std::endl;
    
    		ReleaseSemaphore(full_sem, 1, NULL);
    	}
    	
    	return 0;
    }
    
    int main(){ 
    	
    	full_sem = CreateSemaphore(NULL, 0, QUEUE_LENGTH, NULL);//创建信号量 初始值为0,最大值为QUEUE_LENGTH
    	empty_sem = CreateSemaphore(NULL,QUEUE_LENGTH,QUEUE_LENGTH,NULL);
    
    	DWORD pro_id;//pid
    	DWORD con_id;
    
    	HANDLE producer = CreateThread(NULL, 0, PRODUCER, NULL, 0, &pro_id);//创建线程
    	//Sleep(1000);//展示堵塞
    	
    	HANDLE consumer = CreateThread(NULL, 0, CONSUMER, NULL, 0, &con_id);
    
    	WaitForSingleObject(producer, INFINITE);
    	WaitForSingleObject(consumer, INFINITE);//等待线程运行完成
    
    	CloseHandle(producer);
    	CloseHandle(consumer);//关闭内核对象
    	
    }



  • 相关阅读:
    mybatis-day1
    java基础
    pytest进阶之html测试报告
    pycharm在github上clone项目
    selenium中的显示等待WebDriverWait与条件判断expected_conditions举例
    pytest-html报告中添加报错截图
    Fiddler抓包工具如何设置过滤域名
    os.system运行cmd命令时,命令中嵌套了引号
    Pytest之模块之间共享skipif标记
    Pycharm出现同一目录的py文件不能相互调用的问题
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7109893.html
Copyright © 2011-2022 走看看