四个线程写四个文件03 跨平台实现(Boost)

退出的时候,主线程在iCurr+1之后再唤醒各个子线程。这样做的好处是:防止子线程在主线程改变iCurr的值之前检测循环退出的条件,然后陷入无限的等待中。

#include<ctime>    
#include<cstdio>    
#include<iostream>    
#include <fstream>    
using namespace std;    

#include <boost/thread.hpp>      
#include <boost/thread/mutex.hpp>      
#include <boost/asio/io_service.hpp>        
#include <boost/asio.hpp>        
using namespace boost;    

typedef boost::mutex CMutex;  
CMutex oMutexConsole;  
const int iThreadCnt = 4;//线程的个数    

bool bChildIsWriting[iThreadCnt] = {false, false, false, false};    
/* 
子线程写数字到文件之前:bChilds[i] = false; 
子线程写数字到文件的过程中:bChilds[i] = true;     
子线程写数字到文件之后:bChilds[i] = false;  
*/  
boost::mutex muForLock;//互斥量    
boost::condition_variable cvMain;//主线程通知子线程的条件变量    
std::ofstream oFiles[iThreadCnt];//四个输出文件流    
const int iTimes = 10;//每个线程输出数字序列的长度    
int iCurr = 0;//当前输出数字的个数    


//可变参数列表函数      
void ConsoleOutput(bool bClient, char* lpszFmt, ...){      
	//主线程输出:FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE      
	//客户端线程输出:FOREGROUND_RED      
	//服务器线程输出:FOREGROUND_GREEN      
	va_list pArgLst;        

	va_start(pArgLst, lpszFmt);        
	oMutexConsole.lock();        
	if(bClient)     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);            
	else                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);      
	vfprintf(stdout, lpszFmt, pArgLst);        
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);         
	oMutexConsole.unlock();        
	va_end(pArgLst);        
}      

void WriteNumberIntoTxt(const int writedata){    
	int iFileNo = writedata;//每个线程要写的数字【始终如一】    
	while(iCurr < iTimes){    
		mutex::scoped_lock oLock(muForLock);     
		//初始的时候,条件不满足,所有子线程都陷入了等待中    
		while(!bChildIsWriting[writedata-1]){cvMain.wait(oLock);}    
		this_thread::sleep(posix_time::seconds(rand()%2)); //模拟实际运行中可能遇到的阻塞   
		iFileNo = (iFileNo+3)%iThreadCnt;  //确定要写的文件【每个线程都不一样】  
		oFiles[iFileNo] << writedata << " ";  //开始写  
		bChildIsWriting[writedata-1] = false;  //为下一轮一起写文件做好准备  
	}    
	ConsoleOutput(true, "Thread%d Exits\n", writedata);    
}    

void main()    
{    
	const char* lpszFileName[iThreadCnt] = {"A.txt", "B.txt", "C.txt", "D.txt"};    
	boost::thread oThreads[iThreadCnt];    
	for(int i = 0; i < iThreadCnt; i++){    
		//打开文件【如果不存在则创建】    
		oFiles[i].open(lpszFileName[i], std::ios_base::trunc);    
		//创建线程【传递的参数为线程要写的数字】    
		oThreads[i] = boost::thread(WriteNumberIntoTxt, i+1);    
	}    

	srand((unsigned)time(NULL));//设置随机数的种子    

	for(; iCurr < iTimes;){    
		ConsoleOutput(false, "MainThread is Waiting...\n");    
		//只要还有一个子线程没写完文件,就一直等下去  
		while(bChildIsWriting[0] || bChildIsWriting[1] || bChildIsWriting[2] || bChildIsWriting[3]){boost::this_thread::yield();}    
		{    
			mutex::scoped_lock oLock(muForLock);    
			//让所有的子线程开始写
			for(int i = 0; i < iThreadCnt; i++)      bChildIsWriting[i] = true;    
			//子线程可能在检测到退出条件(iCurr >= iTimes)之前陷入阻塞,无限等待  
			iCurr++;//让每个子线程都满足退出的条件再唤醒  
			    
			cvMain.notify_all(); //唤醒所有被阻塞的子线程   
		}    
		ConsoleOutput(false, "This round is %d.\n", iCurr);    
	}    
	//等待线程执行结束    
	for(int i = 0; i < iThreadCnt; i++)          oThreads[i].join();    
	//关闭所有文件    
	for(int i = 0; i < iThreadCnt; i++)          oFiles[i].close();    
}    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值