`
mmdev
  • 浏览: 12925034 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

QNX多线程同步之Semaphore

 
阅读更多

之前讲了QNX上Mutex的使用,Mutex作用是锁住一个资源,保证同一时间只有一个线程可以使用该资源。不过,有些情况下Mutex不能满足需求,比如某个资源可以允许两个线程同时访问,但是不允许超过两个线程访问它。这种情况下如果还是使用Mutex的话只有一个线程可以访问该资源,没有充分利用允许两个线程访问的属性。Semaphore就适合这种情况,Semaphore翻译成“信号灯”,主要是通过信号灯的数量控制访问资源的线程数。

下面通过一个形象一点的例子说明Semaphore的使用。

假设有3个连队的士兵要通过一座桥,不过这座桥同时只能有两个人通过,有三个人通过的话就会垮掉。士兵们知道了桥的情况,所以在连队内做了规定,士兵们排队通过,只有前面的士兵通过桥之后,排在后面的一个士兵才能上桥。

不过连队内的规定并不能解决问题,虽然3个连队的士兵都按连队内的规定逐个通过,但是连队之间没有协定,3个连队的第一个士兵都走上了桥,桥就垮了。因此,需要在连队之间再做一个协定(这就是多线程同步了)。

就假设军队里有个厉害的工兵,在桥上安装了个信号灯装置(就是Semaphore了),桥头有个按钮,桥尾有个按钮,桥头的按钮按一下桥上就亮起一盏灯,桥尾的按钮按一下桥上就灭一盏灯。

有了这个装置,剩下的就是给连队下规定了,规定每个连队派人上桥之前要确定桥上的灯不能亮两盏(当然也不能是两盏以上)。如果两盏灯都是亮的,必须等待到有灯灭了才可以上桥。同时,士兵上桥之前要按一下桥头的按钮,下桥的时候要按一下桥尾的按钮。

这样,3个连队的士兵都可以安全过桥了,前提是大家都按规定使用信号灯。

另外,如果桥加固了,可以允许4个人同时通过,只需要规定亮的灯是4盏以下才可以上桥。这就是信号灯的数量。

好,回到代码实现上。

首先,如果要使用Semaphore的话,需要引入semaphore.h头文件:

#include <semaphore.h>

然后需要定义一个全局的sem_t变量:

sem_t sem;

然后需要在使用Sempaphore之前对它进行初始化工作,调用的是sem_init方法,第一个参数是定义的sem_t变量,第二个参数先不理,给个0就好了,第三个参数是信号灯的数量,如上例的话就是2(同时只允许2个人通过),代码如下:

sem_init( &sem, 0, 2);

等待信号灯的方法是sem_wait,参数是定义的sem_t变量。注意这个方法包括了上面示例的几个动作,一个是上桥要看信号灯是不是亮了两盏,是的话就等待,不是的话就按一下桥头的按钮,然后上桥。

sem_wait(&sem);

按灭信号灯的方法是sem_post,参数也是定义的sem_t变量:

sem_post(&sem);

完整代码附在后面。其中的onBridge变量用于记录桥上有几个人在走,纯粹是为了说明信号灯使用的效果,不是Semaphore使用所需要的。而主线程的工作就是启动3个线程调用semFunction1方法,模拟3个连队,启动所有子线程后是一个死循环,不断查看onBridge变量,如果onBridge变量大于2则报警。当然,使用了Semaphore之后,onBridge变量是不会大于2的。同学们可以将sem_wait和sem_post注释掉看看没有使用Semaphore的效果。

#include <stdlib.h>

#include <stdio.h>

#include <pthread.h>

#include <semaphore.h>

sem_t sem;

int onBridge=0;

void* semFunction1(void* arg) {

int i=0;

for (i=0;i<20;i++)

{

printf("waiting a sem \n");

sem_wait(&sem);

printf("one soldier walking through the bridge\n");

onBridge++;

sleep(1);

printf("one soldier left the bridge\n");

onBridge--;

printf("posting a sem \n");

sem_post(&sem);

}

return 0;

}

int main(int argc, char *argv[]) {

printf("Starting Semaphore Test\n");

sem_init( &sem, 0, 2);

pthread_create( NULL, NULL, &semFunction1, NULL );

pthread_create( NULL, NULL, &semFunction1, NULL );

pthread_create( NULL, NULL, &semFunction1, NULL );

while(1)

{

if (onBridge>2)

{

printf("%d people on the bridge,the bridge is falling down.\n",onBridge);

}

else

{

printf("%d people on the bridge,it is save.\n",onBridge);

}

delay(200);

}

return 0;

return EXIT_SUCCESS;

}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics