程序描述:
主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 -> sleep-> 全局变量++ -> sleep -> 输出参数和全局变量。
要求:
1.子线程输出的线程序号不能重复。
2.全局变量的输出必须递增。
下面画了个简单的示意图:
分析下这个问题的考察点,主要考察点有二个:
1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。
2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。
实现代码如下:
#include<ctime>
#include<cstdio>
#include<iostream>
#include <fstream>
using namespace std;
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/condition_variable.hpp>
using namespace boost;
typedef boost::mutex CMutex;
typedef boost::condition_variable_any CCondVar;
typedef boost::lock_guard<CMutex> CLockGuard;
typedef boost::unique_lock<CMutex> CUniqueLock;
class CSemaphore{
private:
int iResCnt;
CMutex oMutex;
CCondVar oCondVar;
public:
explicit CSemaphore(unsigned int res = 0) : iResCnt(res){}
void Release(){
{
CLockGuard oLockGuard(oMutex);
iResCnt = iResCnt + 1;
}
oCondVar.notify_one();
}
void WaitFor(){
CUniqueLock oUniqueLock(oMutex);
while(iResCnt == 0){
oCondVar.wait(oUniqueLock);
}
iResCnt = iResCnt - 1;
}
};
long lGlobVar = 0;//全局资源,各线程间互斥访问
CMutex oMutexGlobVar;//互斥量:守护全局变量
CSemaphore oSemaphorePtrParam;//信号量:主线程与子线程之间的同步
void ThreadProc(void* threadno){
//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
int iThreadNo = *(int*)threadno;
oSemaphorePtrParam.Release();//信号量++
this_thread::sleep(posix_time::seconds(rand()%5));
oMutexGlobVar.lock();
lGlobVar++;//处理全局资源
this_thread::sleep(posix_time::seconds(rand()%3));
cout << "线程编号:" << iThreadNo << ",全局变量:" << lGlobVar << endl;
oMutexGlobVar.unlock();
}
void main()
{
srand((unsigned)time(NULL));//设置随机数的种子
boost::thread oThreads[10];
for(int i = 0; i < 10; i++){//等子线程接收到参数时主线程可能改变了这个
//创建线程【传递的参数为线程编号】
oThreads[i] = boost::thread(ThreadProc, &i);
oSemaphorePtrParam.WaitFor();//等待信号量>0 ,信号量--
}
//保证子线程已全部运行结束
for(int i = 0; i < 10; i++) oThreads[i].join();
}
运行结果如下: