使用Win32 API实现生产者消费者线程同步

Posted brucemengbm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用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);//关闭内核对象
	
}









以上是关于使用Win32 API实现生产者消费者线程同步的主要内容,如果未能解决你的问题,请参考以下文章

转载使用Win32API实现Windows下异步串口通讯

通过Lock对象以及Condition对象实现多线程同步

win32多线程设计总结

用c语言或c++编写编程实现生产者消费者或读写者的同步问题

生产者消费者模型

从生产者消费者窥探线程同步(下)