多线程相关的编程,有很多说法,有人说应该去除,因为他带了了潜在的安全性,但有人有建议保留,因为他充分利用了cpu,只要我们注意其中的安全问题,所以多线程可以为我们造福,所以关于多线程编程,我们应该更多注意安全性的问题!
1.创建一个线程
(1)利用CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreateionFlag,
LPDWORD lpTHreadId
)
第一个参数:在一般情况下设置为NULL
第二个参数:设置线程堆栈大小。通常设置为0,表示使用默认大小。
第三个参数:指向线程函数的指针
第四个参数:想线程函数传递的参数,是一个LPVOID指针类型。如果不需要传递参数,设置为NULL
第五个参数:创建线程标志,当为CREATE_SUSPENED时,表示创建后线程刮起(需要启动线程,调用ResumeThread()即可);当为0时,表示创建后线程立即执行。
第六个参数:保存当前新线程的ID.
(2)DWORD WaitForsingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
)
第一个参数:一个事件的句柄,在本例中是线程句柄。
第二个参数:等待时间间隔。如果永久等待,则设置为INFINITE,在本例中等待5000豪秒
此函数返回 三个值:WAIT_OBJECT_0 (核心对象已被激活),WAIT_TIMEOUT(等待超时),WAIT_FAILED(出现错误)。
(3)我们写了一个win32console的程序,见如下:
// 创建线程.cpp : #include "stdafx.h"
#include<windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI TestThreadProc(LPVOID pParam);
int main(int argc, char* argv[])
{
DWORD dwThreadId = 0;
const int nMaxCount = 100;
HANDLE hThread = CreateThread(NULL,0UL,TestThreadProc,(void*)&nMaxCount,0,&dwThreadId);
WaitForSingleObject(hThread,5000);//主线程等待5秒
CloseHandle(hThread);
return 0;
}
DWORD WINAPI TestThreadProc(LPVOID pParam)
{
const int nMax = *(int *)pParam;
for ( int i=0;i<nMax;i++)
{
cout << i<<endl;
Sleep(100);
}
return 0;
}
2.线程的挂起和唤醒
当主线程希望次工作线程暂停时,需要调用函数DWORD SuspendThread(HANDLE hThread)将此工作线程挂起。相反,当希望一个挂起的工作线程重新运行,调用函数DWORD ResumThread(HANDL hThread)将恢复线程工作。最后可以利用closeHandle(HANDLE hThread)关闭掉一个线程句柄,但并非终止。
同样也是一个win32程序,演示线程先运行5秒,然后将线程挂起,然后睡眠3秒,然后唤醒恢复线程!
// 线程的挂起与恢复.cpp :#include "stdafx.h"
#include<windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI TestThreadProc(LPVOID pParam);
int main(int argc, char* argv[])
{
DWORD dwThreadID = 0;
const int nMaxCOunt = 100;
//创建线程,线程入口地址为TestThreadProc,传入参数为(void*)&nMaxCount
//返回线程句柄为hThread,其创建线程的ID为dwThreadId;
HANDLE hThread = CreateThread(NULL,0UL,TestThreadProc,(void*)&nMaxCOunt,0,&dwThreadID);
//等待5000毫秒,如果线程退出,则返回0
if ( WAIT_OBJECT_0 == WaitForSingleObject(hThread,5000))
{
return 0;
}
SuspendThread( hThread);//挂起线程
Sleep(3000);//睡眠3秒
ResumeThread(hThread);//唤醒线程
WaitForSingleObject(hThread,INFINITE);//一直等待线程结束为止
CloseHandle(hThread);//关闭线程句柄
return 0;
}
DWORD WINAPI TestThreadProc(LPVOID pParam)
{
const int nMax = *(int*)pParam;
for (int i=0;i<nMax;i++)
{
cout << i <<" "<<endl;
Sleep(100); //每隔100毫秒打印一次
}
cout<<"线程执行完毕!"<<endl;
return 0;
}
3.终止一个线程
有两种,一种是非常野蛮方法,及函数BOOL TerminateThread(HANDLE hThread,DWORD wExitCode),此方法不再外不得已的情况下,不建议使用!
第二种方法,可以设置一个全局变量,也可以设置一个结束时间,当我们要结束线程时,设置为false,那么线程跳出,自动终止!
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI TestThreadProc(LPVOID pParam);
BOOL bTerminate;
int main(int argc, char* argv[])
{
DWORD dwThreadId;
bTerminate = FALSE;
const int nMaxCnt = 100;
HANDLE hThread = CreateThread(NULL, 0, TestThreadProc, (LPVOID)&nMaxCnt, CREATE_SUSPENDED, &dwThreadId);
if(hThread == INVALID_HANDLE_VALUE)
{
return -1;
}
ResumeThread(hThread);
if(WAIT_OBJECT_0 == WaitForSingleObject(hThread, 3000)) return -1;
bTerminate = TRUE;
WaitForSingleObject(hThread, INFINITE);
return 0;
}
DWORD WINAPI TestThreadProc(LPVOID pParam)
{
const int nMax = *(int*)pParam;
for(int i = 0; i < nMax; i++)
{
if(bTerminate)
{
cout << "收到线程终止命令!" << endl;
break;
}
cout << "the number is " << i << endl;
Sleep(100);
}
cout << "线程执行结束!" << endl;
return 0;
}
4.CEvent类的使用,待续!
5.CCriticalSection类的使用
CCritcalSection即临界区,主要用作当某个时间内只允许最多一个线程修改某些数据或其他一些资源时,比如在某个时间内只允许最多一条线程去完成,对于链表改变节点数据的操作,应该用CCriticalSection对象控制,也就是说,在某个时间点上至多只有一个线程允许在这个链表上增加,删除,修改!
本例也是Win32的一个例子。
(1)首先修改Project-Setting-General-Microsoft Fondation—该为Use MFC as Static Library
( 2 )定义一个CCriticalSection cs对象
(3)对你要保护的代码段之前套上,cs.lock() 和 cs.Unlock();
// 如何使用CCriticalSection.cpp :
#include "stdafx.h"
#include <afxmt.h>
CCriticalSection cs;
DWORD WINAPI CSTestThread1(LPVOID pParam);
DWORD WINAPI CSTestThread2(LPVOID pParam);
DWORD WINAPI CSTestThread3(LPVOID pParam);
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
HANDLE hThread[3];
DWORD dwThreadId[3];
hThread[0] = CreateThread(NULL,0UL,CSTestThread1,NULL,0,&dwThreadId[0]);
hThread[1] = CreateThread(NULL,0UL,CSTestThread2,NULL,0,&dwThreadId[1]);
hThread[2] = CreateThread(NULL,0UL,CSTestThread3,NULL,0,&dwThreadId[2]);
WaitForMultipleObjects(3,hThread,TRUE,INFINITE);//等三个线程
for ( int i=0;i<3;i++)
{
CloseHandle(hThread[i]);
}
return 0;
}
DWORD WINAPI CSTestThread1(LPVOID pParam)
{
for(int i = 0; i < 5; i++)
{
cs.Lock();
cout << "I am the thead one" << endl;
cs.Unlock();
Sleep(2000);
}
return 0UL;
}
DWORD WINAPI CSTestThread2(LPVOID pParam)
{
for(int i = 0; i < 5; i++)
{
cs.Lock();
cout << "I am the thead two" << endl;
cs.Unlock();
Sleep(2000);
}
return 0UL;
}
DWORD WINAPI CSTestThread3(LPVOID pParam)
{
for(int i = 0; i < 5; i++)
{
cs.Lock();
cout << "I am the thead three" << endl;
cs.Unlock();
Sleep(2000);
}
return 0UL;
}
6.如何使用CSemaphore类
CSemphore叫信号量,也称作信号灯。相当于一个计数器,用于限制可使用资源线程的数目。比如某一间事情,考虑到程序运行的性能问题,规定同时最多不超过6个线程完成任务,这时就需要用到信号量。信号量允许多个线程同时使用共享资源,他规定了同时访问共享资源的线程最大数目。
(1)CSemaphore(
LONG lInitialCount =1 ,
LONG lMaxCount = 1,
LPCTSTR pstrName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes = NULL
)
第一个参数:信号量对象的初始计数值,即颗访问线程数目的初始值,取值不得大于lMaxCount且不得小于0(可等于0);
第二个参数:信号量对象计数值的最大值,该参数决定了同一时刻可访问由信号量保护的资源线程最大数目。
(2)DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
hHandle [in]对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
dwMilliseconds [in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle 标记的对象被触发,或者时间到了。
如果dwMilliseconds 为0,对象没有被触发信号,函数不会进入一个等待状态,
它总是立即返回。如果dwMilliseconds 为INFINITE,对象被触发信号后,函数才会返回。
(3)ReleaseSemaphore(
semaphore->m_hObject,1,NULL) 信号量减少计数1
运用 CSemaphore类,限制可使用资源线程的数目
运用WatiForSingleObject(),等待一个内核对象
运用ReleaseSemaphore()函数是计数器减1
代码如下:
// 如何使用CSemaphore类.cpp : #include "stdafx.h"
#include<afxmt.h> //包含CSemaphore类头文件
CSemaphore *m_pSemaphore; //声明Csemaphore类指针变量,信号量
CCriticalSection cs; //声明CCriticalSection对象,控制共享资源
DWORD WINAPI SemapTestThread1(LPVOID pParam);//声明线程1
DWORD WINAPI SemapTestThread2(LPVOID pParam);//声明线程2
DWORD WINAPI SemapTestThread3(LPVOID pParam);//声明线程3
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
HANDLE hTread[3];
DWORD dwThreadId[3];
m_pSemaphore = new CSemaphore(2,2);
hTread[0] = CreateThread(NULL,0UL,SemapTestThread1,NULL,0,&dwThreadId[0]);
hTread[1] = CreateThread(NULL,0UL,SemapTestThread2,NULL,0,&dwThreadId[1]);
hTread[2] = CreateThread(NULL,0UL,SemapTestThread3,NULL,0,&dwThreadId[2]);
WaitForMultipleObjects(3,hTread,TRUE,INFINITE);
for ( int i= 0;i< 3; i++)
{
CloseHandle(hTread[i]);
}
return 0;
}
DWORD WINAPI SemapTestThread1(LPVOID pParam)
{
WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);
cs.Lock();
cout<<"I am the thread one" <<endl;
cs.Unlock();
Sleep(3000);
ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);
return 0UL;
}
DWORD WINAPI SemapTestThread2(LPVOID pParam)
{
WaitForSingleObject(m_pSemaphore->m_hObject, INFINITE);
cs.Lock();
cout << "I am the thread two" << endl;
cs.Unlock();
Sleep(3000);
ReleaseSemaphore(m_pSemaphore->m_hObject, 1, NULL);
return 0UL;
}
DWORD WINAPI SemapTestThread3(LPVOID pParam)
{
WaitForSingleObject(m_pSemaphore->m_hObject, INFINITE);
cs.Lock();
cout << "I am the thread three" << endl;
cs.Unlock();
Sleep(3000);
ReleaseSemaphore(m_pSemaphore->m_hObject, 1, NULL);
return 0UL;
}
7.如何使用CSingleLock类
CSingleLock类通常被作为等待和释放的同步对象。所谓同步对象就是指上面几个实例讲解的CSemaphore,CMutex,CCriticalSection和CEvent。本实例以CSingleLock操作CSemaphore对象为例。
其实这个类,有点像考察官,就是你传给它一个考察的对象,如果该信号有了,那么他就来告诉你,Ok,你可以做事情了!
(1)CSingleLock(
CSynCObject* pObject,
BOOL bInitialLock = FALSE
)
第一个参数:需要等待或释放的同步对象指针
第二个参数:同步对象的初始状态。
(2)CSingleLock:Lock(
DWORD dwTimeOUt = INFINITE //等待同步对象有信号的最多时间,单位毫秒
)
#include "stdafx.h"
#include <iostream>
using namespace std;
DWORD WINAPI UseSingleLockThread(LPVOID pParam);
CSemaphore m_Semaphore(2,2); //信号灯
CEvent m_Event(FALSE,FALSE);//事件
CCriticalSection cs; //临界区保护
int main(int argc, char* argv[])
{
int i;
HANDLE hThread[9];
DWORD dwThreadId;
for( i = 0; i < 9; i++)
{
m_Event.ResetEvent(); //设置事件为无信号
hThread[i] = CreateThread(NULL, 0, UseSingleLockThread, (LPVOID)&i, CREATE_SUSPENDED, &dwThreadId);
ResumeThread(hThread[i]);//唤醒线程
CSingleLock lock(&m_Event);
lock.Lock();//等待事件对象,如果没有消息,则一直等待
}
WaitForMultipleObjects(9, hThread, TRUE, INFINITE);//同时等待9个对象
for( i = 0; i < 9; i++)
{
CloseHandle(hThread[i]);
}
return 0;
}
DWORD WINAPI UseSingleLockThread(LPVOID pParam)
{
int i = *(int*)pParam; //得到创建线程传出的参数
m_Event.SetEvent(); //设置时间对象为有 信号状态
CSingleLock lock(&m_Semaphore);
lock.Lock();//等待事件
cs.Lock();//进入临界区
cout << "I am the thread " << i << endl;
cs.Unlock();//离开临街区
Sleep(2000);//挂起线程2秒
return 0UL;
}
8.如何使用CMutex
CMutex即互斥量。互斥量对象与临界区对象很相似,互斥对象和临界对象区都可以用于各个线程间。当然,在这种情况下使用临界区会更节省系统资源,而且更有效率。但是互斥对象可以在进程间使用,而临界区对象只能在同一进程的各线程间使用。
本例程序建立一个名为Mutex_1的互斥量对象和一个初始无信号的时间对象。然后互斥量进入进程互斥,建立一个线程且该线程的作用是20秒后设置时间为m_Event事件,直到有信号为止。编译该程序,开启两个exe,我们可以ikan到,最先开启的进程会打印两行文字,而第二个进程只打印一行,要等待20秒后才打印出第二行文字,这说明CMutex可以在进程间使用。
#include "stdafx.h"
#include <afxmt.h>
char szMutexText[] = "Mutex_1";
CMutex m_Mutex(FALSE, szMutexText);
DWORD WINAPI UnlockMutex(LPVOID pParam);
CEvent m_Event(FALSE, FALSE);
#include <iostream>
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
cout << "程序进入MAIN函数." << endl;
m_Mutex.Lock();
cout << "程序过入互斥量." << endl;
m_Event.ResetEvent();
HANDLE hThread = CreateThread(NULL, 0, UnlockMutex, NULL, 0, NULL);
WaitForSingleObject(m_Event.m_hObject, INFINITE);
m_Mutex.Unlock();
return 0;
}
DWORD WINAPI UnlockMutex(LPVOID pParam)
{
Sleep(20000);
m_Event.SetEvent();
return 0UL;
}
9.线程的消息队列
本例通过线程消息队列介绍线程消息的一些知识,主要PostThreadMessage()向线程发送信息,然后使用GetMessage()获取并解析。
(1)BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax)
参数解析:
lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。这是一个有特殊含义的值(NULL)。GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
返回值:除消息WM_QUIT外返回非0,否则返回0
(2)BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM IParam);
参数:
第一个:其消息将被寄送的线程的ID,如果该线程没有消息队列,此函数将调用失败。
第二个:指定将被寄送的消息类型
第三个:附加消息
第四个:附加消息
返回值:如果调用成功返回TRUE,否则返回FALSE.
实现步骤
(1)首先为DLg类添加两个变量:
HANDLE m_hThread;
DWORD m_dwThreadId;
(2)然后在OnInitDlg函数中实现如下:
BOOL CMyDlg::OnInitDialog()
{
m_hThread = CreateThread(NULL, 0UL, TestMessageThread, NULL, CREATE_SUSPENDED, &m_dwThreadId);
if(m_hThread == INVALID_HANDLE_VALUE)
{
AfxMessageBox("创建线程失败!");
return TRUE;
}
ResumeThread(m_hThread);
return TRUE; // return TRUE unless you set the focus to a control
}
(3)然后我们定义几个消息,在Dlg.cpp的顶部
#define WM_USERMESSAGE1 WM_USER + 0x100 //第一个消息
#define WM_USERMESSAGE2 WM_USER + 0x106 //第二个消息
#define WM_USERMESSAGE3 WM_USER + 0x109 //第三个消息
DWORD WINAPI TestMessageThread(LPVOID pParam); //线程
(4)线程的实现函数:
DWORD WINAPI TestMessageThread(LPVOID pParam)
{
MSG msg;
CString strText;
while(GetMessage(&msg, NULL, 0U, 0U))
{
switch(msg.message)
{
case WM_USERMESSAGE1:
{
char *p = (char*)msg.lParam;
if(p != NULL)
{
strText.Format("收到Button1的消息为:\"%s\"", p);
delete p;
AfxMessageBox(strText);
}
}
break;
case WM_USERMESSAGE2:
{
int *pn = (int*)msg.lParam;
if(pn != NULL)
{
strText.Format("收到Button2的整型数:%d", *pn);
delete pn;
AfxMessageBox(strText);
}
}
break;
case WM_USERMESSAGE3:
{
double *pd = (double*)msg.lParam;
if(pd != NULL)
{
strText.Format("收到Button3的双精度浮点数:%lf", *pd);
delete pd;
AfxMessageBox(strText);
}
break;
}
default:
break;
}
DispatchMessage(&msg);
TranslateMessage(&msg);
}
return 0UL;
}
(5)为各个button控件添加响应函数,发送不同的消息:
void CMyDlg::OnButton1()
{
//向线程传入消息和参数
char *p = new char[MAX_PATH];
strcpy(p, "这是第一个按钮参入的字符串消息!");
PostThreadMessage(m_dwThreadId, WM_USERMESSAGE1, NULL, (LPARAM)p);
}
void CMyDlg::OnButton2()
{
int *n = new int;
*n = 200;
PostThreadMessage(m_dwThreadId, WM_USERMESSAGE2, NULL, (LPARAM)n);
}
void CMyDlg::OnButton3()
{ double *fl = new double;
*fl = 3.1415926;
PostThreadMessage(m_dwThreadId, WM_USERMESSAGE3, NULL, (LPARAM)fl);
}
实力:生产者-消费者。
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <ctime>
using namespace std;
#define BUFFER_SIZE 5
typedef int buffer_item;
buffer_item buffer[BUFFER_SIZE];
int number;
int in=0;
int out=0;
buffer_item total=0;
HANDLE Mutex = CreateMutex(NULL,FALSE,NULL); //Win32 API中的Mutex Lock 用于各个生产者、消费者间的互斥
HANDLE mutex = CreateSemaphore(NULL,1,1,NULL);//Win32 API中的Semaphore 用于各个生产者、消费者间的互斥
HANDLE empty = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);//Win32 API中的Semaphore 用于同步缓冲区满
HANDLE full = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL);//Win32 API中的Semaphore 用于同步缓冲区空
int insert_item(buffer_item item)
{
if( (total == BUFFER_SIZE) && (number==0)) //如果采用Mutex方法且插入时发现缓冲区满,就丢弃此item
{
return 1;
}
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
total++;
return 0;
}
int remove_item(buffer_item *item)
{
if ( (total == 0) && (number==0)) //如果采用Mutex方法且插入时发现缓冲区空,就忽略此次remove请求
{
return 1;
}
*item = buffer[out];
buffer[out]=0;
out = (out + 1) % BUFFER_SIZE;
total--;
return 0;
}
DWORD WINAPI producer (LPVOID Prama) //生产者进程的入口函数
{
buffer_item produce_item;
int sleeptime;
int index;
DWORD producer_ID = *(DWORD*) Prama;
while (TRUE)
{
sleeptime= 1000+ rand()%2000;
Sleep(sleeptime);
produce_item = 1+rand()%9; //生产者经过随机时间产生一个随机的item
if(number==0) //Mutex方法
{
WaitForSingleObject(Mutex,INFINITE);
}
else //Semaphore方法
{
WaitForSingleObject(empty,INFINITE);
//WaitForSingleObject(mutex,INFINITE);
WaitForSingleObject(Mutex,INFINITE);
}
if (insert_item(produce_item)) //输出插入信息
{
cout<<"Producer "<<producer_ID<<" produced item "<<produce_item<<" but full!";
for (index=0;index<BUFFER_SIZE;index++)
{
cout<<" "<<buffer[index];
}
cout<<endl;
}
else
{
cout<<"Producer "<<producer_ID<<" produced item "<<produce_item<<" insert OK!";
for (index=0;index<BUFFER_SIZE;index++)
{
cout<<" "<<buffer[index];
}
cout<<endl;
}
if(number==0) //Mutex方法解锁
{
ReleaseMutex(Mutex);
}
else //Semaphore方法解锁
{
//ReleaseSemaphore(mutex,1,NULL);
ReleaseMutex(Mutex);
ReleaseSemaphore(full,1,NULL);
}
}
return 0;
}
DWORD WINAPI consumer(LPVOID Prama) //消费者进程的入口函数
{
buffer_item consumer_item;
int sleeptime;
int index;
DWORD consumer_ID = *(DWORD*) Prama;
while (TRUE)
{
sleeptime= 1000+ rand()%3000;
Sleep(sleeptime); //消费者经过随机时间后请求消费
if(number==0) //Mutex方法
{
WaitForSingleObject(Mutex,INFINITE);
}
else //Semaphore方法
{
WaitForSingleObject(full,INFINITE);
//WaitForSingleObject(mutex,INFINITE);
WaitForSingleObject(Mutex,INFINITE);
}
if (remove_item(&consumer_item)) //输出移除后的信息
{
cout<<"Consumer "<<consumer_ID<<" wants consume but empty!";
for (index=0;index<BUFFER_SIZE;index++)
{
cout<<" "<<buffer[index];
}
cout<<endl;
}
else
{
cout<<"Consumer "<<consumer_ID<<" wants consume remove "<<consumer_item<<" OK!";
for (index=0;index<BUFFER_SIZE;index++)
{
cout<<" "<<buffer[index];
}
cout<<endl;
}
if(number==0) //Mutex方法解锁
{
ReleaseMutex(Mutex);
}
else //Semaphore方法解锁
{
//ReleaseSemaphore(mutex,1,NULL);
ReleaseMutex(Mutex);
ReleaseSemaphore(empty,1,NULL);
}
}
return 0;
}
int main()
{
srand( (unsigned)time(0) );
int numProducers; //生产者数目
int numConsumers; //消费者数目
cout<<"Opearting System Experiment: Producer & Consumer."<<endl;
cout<<"Realizing with Win32 API"<<endl;
cout<<"0 Mutex , 1 Semaphore(others to end): ";
cin>>number;
if (number!=0 && number!=1)
{return 0;}
if (number==0)
{
cout<<"****************************Mutex Approach****************************"<<endl;
}
else
cout<<"****************************Semaphore Approach****************************"<<endl;
cout<<"Buffer Init: ";
for (int i=0; i<BUFFER_SIZE; i++)
{
buffer[i]=0;
cout<<"\t"<<buffer[i];
}
cout<<endl;
cout<<"Input the number of Producers: ";
cin>>numProducers;
cout<<"Input the number of Consumers ";
cin>>numConsumers;
HANDLE* Producers=new HANDLE[numProducers];
HANDLE* Consumers=new HANDLE[numConsumers];
for (DWORD j=0; j<numProducers; j++)
{
Producers[j]=CreateThread(NULL,0,producer,&j,0,NULL); //生成生产者进程,传递进程函数
}
for (DWORD k=0; k<numConsumers; k++)
{
Producers[k]=CreateThread(NULL,0,consumer,&k,0,NULL); //生成消费者进程,传递进程函数
}
Sleep(8000);
return 0;
}
这样我们就创建了一个线程,不断的接收我们发送的各种消息!