`

多线程编程

 
阅读更多

   多线程相关的编程,有很多说法,有人说应该去除,因为他带了了潜在的安全性,但有人有建议保留,因为他充分利用了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;
	
}

 

 这样我们就创建了一个线程,不断的接收我们发送的各种消息!

 

分享到:
评论

相关推荐

    Linux下C语言多线程编程实例

    Linux 下 C 语言多线程编程实例 Linux 下的多线程编程是一种非常重要的技术,在实际应用中有非常广泛的应用范围。多线程编程可以大大提高程序的执行效率和响应速度。但是,多线程编程也存在一些复杂性,例如线程...

    Linux下的多线程编程.pdf

    "Linux下的多线程编程" Linux下的多线程编程是一种高效的程序设计方法,它可以将一个程序的任务划分为多个部分,每个部分是一个顺序控制流。多线程编程可以实现并行计算,高效利用多处理器,并且具有许多优点,如...

    C#多线程编程实例实战.pdf

    C#多线程编程实例实战 C#多线程编程实例实战是指在C#语言中实现多线程编程的实例和实战经验。多线程编程是指在同一个进程中创建多个线程,以便提高程序的执行效率和响应速度。在C#语言中,可以使用Thread类和线程池...

    linux多线程编程手册.pdf

    "Linux 多线程编程手册" 本手册为 Linux 多线程编程提供了详细的指导,涵盖了多线程基础介绍、多线程术语定义、多线程标准、多线程的益处、提高应用程序的响应、有效使用多处理器等方面的内容。 1. 多线程基础介绍...

    JAVA多线程编程技术PDF

    这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点。 首先,多线程的核心概念包括线程的创建与启动。在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后...

    Windows多线程编程技术与实例(C++)(PDF)

    《Windows多线程编程技术与实例(C++)》是一本深入探讨Windows环境下多线程编程的书籍,特别适合正在学习或已经从事C++多线程开发的人员阅读。本书通过丰富的实例,详细讲解了如何在Windows操作系统中利用C++进行...

    汪文君JAVA多线程编程实战(完整不加密)

    《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

    嵌入式软件开发技术:第5章 嵌入式Linux多线程编程.ppt

    嵌入式Linux多线程编程 嵌入式Linux多线程编程是嵌入式系统开发中的一种重要技术,能够提高系统的效率和响应速度。本章节将详细介绍嵌入式Linux多线程编程的基本概念、线程的创建、同步和互斥、线程属性、多线程...

    多线程编程(完整版)

    多线程编程是一种重要的软件开发技术,特别是在处理并发任务、优化资源利用率和提高程序响应速度方面。通过创建多个线程,程序可以在同一进程中并行执行不同的任务,从而提高整体效率。 在操作系统层面,进程和线程...

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    多线程编程指南.pdf

    ### 多线程编程指南:全面解析与应用 #### 多线程编程的定义与重要性 多线程编程是一种让程序能够同时执行多个任务的技术,通过在单一进程中创建多个线程来实现并发操作,从而提高了程序的效率和响应速度。这种...

    C++多线程编程.pdf

    C++多线程编程

    linux多线程编程.pdf

    Linux多线程编程是操作系统中并发程序设计的一个重要领域,它允许开发者在同一程序中创建多个线程,以实现并行执行,从而提高程序的执行效率和响应能力。Linux下的多线程编程通常基于POSIX线程(pthread)库来实现,...

    MFC多线程编程

    【MFC多线程编程】是Windows环境下使用Microsoft Foundation Class (MFC)库进行多线程应用程序开发的技术。MFC库是Visual C++提供的一种面向对象的类库,它简化了Windows API的使用,包括多线程编程。多线程在现代...

    c++多线程编程的十个例子

    以下是对“C++多线程编程的十个例子”的详细讲解,这些例子将帮助你在Windows环境下深入理解和应用多线程。 1. **创建线程** C++11引入了`std::thread`库来创建和管理线程。例如,你可以通过传递函数或成员函数...

    C#多线程编程实战完整源码

    C#多线程编程是开发高效、响应迅速的软件应用的关键技术之一,尤其在现代计算环境中,多核处理器和并发处理的需求日益增加。本资源"《C#多线程编程实战》完整源码"提供了丰富的实例,适用于学习和实践C#中的多线程...

    Linux多线程编程手册

    Linux多线程编程是现代操作系统中应用广泛的编程模式,尤其适用于需要同时执行多个任务的应用程序,它能够在多处理器或多核CPU系统中有效提升程序的执行效率,优化资源利用。多线程编程允许在同一个进程中创建多个...

    C#多线程编程源码奉上

    在这个“C#多线程编程源码”中,我们可以深入学习如何在Visual Studio 2008环境下利用C#进行多线程操作,包括UI线程和异步调用的实现。 1. **多线程基础** - **线程创建**:C#中可以使用`System.Threading.Thread`...

    c#多线程编程实战(原书第二版)源码

    《C#多线程编程实战(原书第二版)源码》是一本深入探讨C#中多线程技术的专业书籍,其源码提供了丰富的实践示例,帮助读者掌握并发编程的核心概念和技术。在C#中,多线程是实现高性能、响应式应用程序的关键组成部分...

Global site tag (gtag.js) - Google Analytics