信号灯

在进程通信当中,我经常会用到信号灯的操作,为此,我小结一下:
信号灯有无名信号灯和有名信号灯,我们仅讨论无名信号灯,

创建信号灯:
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem表示信号灯的一些信息,类似于进程的PCB。
pshared表示是否为多进程所共享,而不仅仅是一个用于一个进程,linux Thread下没有实现多进程的信号灯共享,所以这个值一般为0,否则会返回-1错误值。
value表示信号灯的数量。
注销信号灯:
int sem_destroy(sem_t *sem);
sem表示要注销的信号灯。
获取灯值:
int sem_getvalue(sem_t *sem, int *sval);
读取sem灯的灯计数。
点灯操作:
int sem_post(sem_t *sem);
给灯值原子加1,表示增加了一个可用的资源。
灭灯操作:
int sem_wai(sem_t *sem);
int sem_trywait(sem_t *sem);
这两个都是将信号灯的原子值减1,表示减少一个可用的资源。但这两个也是有区别的:如果当信号灯的原子值小于或等于0,使用sem_trywait()时不会使线程阻塞,而sem_wait()时将会使线程阻塞。

有关信号灯的操作一般都在头文件 当中,下面是人sem_t的结构体定义:
typedef union
{
  char __size[__SIZEOF_SEM_T];
  long int __align;
} sem_t;


一个实例:生产者-消费者(经典IPC问题)

/*
 *Time:2010/9/27
 *Author:Software Engineering
 */

#include <stdio.h>
#include <string.h>
#include <pthread.h> //包含线程操作的一些函数

#include <semaphore.h> //包含信号灯操作的一些函数


#define N 4 //定义缓冲池的数量

#define P_COUNT 3 //定义生产者的数量

#define C_COUNT 3 //定义消费者的数量

int first = 0; //记录缓冲区的下标

char buffer[N][20]; //缓冲区的定义


pthread_mutex_t mutex; //互斥锁

sem_t full, empty; //分别表示缓冲池中的空区和满区的数量


void print()
{
    int i;
    for(i = 0; i < N; i++) {
        printf("%s\t", buffer[i]);
    }
    printf("\n");
}

void *producer()
{
    char *goods = "鸡蛋";
    int count = 8;
    do {
        sem_wait(&empty); //关灯操作

        pthread_mutex_lock(&mutex);
        strcpy(buffer[first++], goods);
        printf("%u生产者:", pthread_self());
        print();
        sleep(1);
        pthread_mutex_unlock(&mutex);
        sem_post(&full); //开灯操作

    } while(count-- > 0);
}

void *customer()
{
    int count = 8;
    do {
        sem_wait(&full); //关灯操作

        pthread_mutex_lock(&mutex);
        strcpy(buffer[--first], "0");
        printf("%u消费者:", pthread_self());
        print();
        sleep(1);
        pthread_mutex_unlock(&mutex);
        sem_post(&empty); //开灯操作

    } while(count-- > 0);
}

int main()
{
    pthread_t tid1, tid2;
    int i;

    //初始化缓冲池

    for(i = 0; i < N; i++) {
        strcpy(buffer[i], "0");
    }

    //创建信号灯

    sem_init(&empty, 0, N);
    sem_init(&full, 0, 0);

    //创建生产者线程和消费者线程

    for(i = 0; i < P_COUNT; i++) {
        pthread_create(&tid1, NULL, producer, NULL);
    }
    for(i = 0; i < C_COUNT; i++) {
        pthread_create(&tid2, NULL, customer, NULL);
    }

    pthread_exit(0);
}


运行的部分结果:
3068443504生产者:鸡蛋    鸡蛋    鸡蛋    0   
3026484080消费者:鸡蛋    鸡蛋    0    0   
3026484080消费者:鸡蛋    0       0     0   
3047463792消费者:0       0      0    0   
3068443504生产者:鸡蛋    0      0    0   
3068443504生产者:鸡蛋    鸡蛋    0    0   
3068443504生产者:鸡蛋    鸡蛋    鸡蛋    0   
3057953648生产者:鸡蛋    鸡蛋    鸡蛋    鸡蛋   
3026484080消费者:鸡蛋    鸡蛋    鸡蛋    0   
3068443504生产者:鸡蛋    鸡蛋    鸡蛋    鸡蛋   
3047463792消费者:鸡蛋    鸡蛋    鸡蛋    0   
3047463792消费者:鸡蛋    鸡蛋    0    0   
3047463792消费者:鸡蛋    0      0    0   
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(752) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值