QSemaphore也是一个线程同步工具,这个工具像是QMutex的升级版。对于QMutex而言,只要一个线程拿到QMutex的使用权,其他线程再想要拿就必须等着。QSemaphore的使用权(或称资源)数量可以是多个,假如设置了QSemaphore的使用权有10个,第一个线程请求了5个剩下5个,第二个线程可以再请求小于等于5个使用权。若第二个线程想要请求8个则会失败,第二个线程只能继续等待其他线程释放资源。
举个公共厕所的例子,假如公共厕所有5个坑,QSemaphore是公共厕所的指示牌,指示牌上有五个指示灯。刚开始的时候灯是全灭的,表示坑都可用。这时候来了一个人,他看到有5个指示灯全是灭的,于是进去占了一个坑,有一盏灯亮了。又过了一会儿来了一对基友,他们看到还有4个指示灯是灭的,于是进去占了两个坑,又有两盏灯亮了。接着又来两人占满了5个坑,5盏灯全亮了。这时候又来了一个人,看到5盏灯全亮了,没办法只能在门外等着,直到里面有人出来,指示灯熄灭。
写个测试代码:
1.定义一个公共数据bool数组,它有5个元素,与之对应的QSemaphore也是5个元素。
2.定义公共数据的使用者Thread(继承于Qthread)。每个Thread都有一个成员变量mId在构造函数中赋值,以示区别。其run函数如下:
run函数的功能是请求资源(gSema()),若请求到资源则去gData中寻找可用的数据并打印,否则等待。当找到可用数据时睡眠3秒(模拟使用过程),最后将使用的数据设置为未使用并释放资源(gSema())。
3.创建100个Thread的对象并start,查看运行结果:
程序每隔3秒输出5个数据被占用的信息。说明请求到资源的线程可以使用,没争到的只能等待了。
题外话:
本例子其实还有个问题,那就是既然资源总数有5个,那么这里就会有5个线程同时去找gData中可用的数据。就好比5个人同时进入公共厕所后还得去抢坑。这里可以在寻找gData前加一个QMutex,表示先来的先找,后来者等待,这样可以确保占坑的顺序。所以说QSemaphore好像是QMutex的升级版,但两者是可以配合使用的。