多线程编程指南

使用信号时的生成方和使用者问题

示例 4–14 中的数据结构与示例 4–11 中所示的用于条件变量示例的结构类似。两个信号分别表示空缓冲区和满缓冲区的数目,通过这些信号可确保生成方等待缓冲区变空,使用者等待缓冲区变满为止。


示例 4–14 使用信号时的生成方和使用者问题

typedef struct {

    char buf[BSIZE];

    sem_t occupied;

    sem_t empty;

    int nextin;

    int nextout;

    sem_t pmut;

    sem_t cmut;

} buffer_t;



buffer_t buffer;



sem_init(&buffer.occupied, 0, 0);

sem_init(&buffer.empty,0, BSIZE);

sem_init(&buffer.pmut, 0, 1);

sem_init(&buffer.cmut, 0, 1);

buffer.nextin = buffer.nextout = 0;

另一对二进制信号与互斥锁作用相同。在多个生成方使用多个空缓冲槽位,以及多个使用者使用多个满缓冲槽位的情况下,信号可用来控制对缓冲区的访问。在这种情况下,使用互斥锁可能会更好,但这里主要是为了演示信号的用法。


示例 4–15 生成方和使用者问题:生成方

void producer(buffer_t *b, char item) {

    sem_wait(&b->empty);

    sem_wait(&b->pmut);



    b->buf[b->nextin] = item;

    b->nextin++;

    b->nextin %= BSIZE;



    sem_post(&b->pmut);

    sem_post(&b->occupied);

}


示例 4–16 生成方和使用者问题:使用者

char consumer(buffer_t *b) {

    char item;



    sem_wait(&b->occupied);

   

    sem_wait(&b->cmut);



    item = b->buf[b->nextout];

    b->nextout++;

    b->nextout %= BSIZE;



    sem_post(&b->cmut);



    sem_post(&b->empty);



    return(item);

}