sem_t的使用步骤

sem_t的使用步骤,第1张

1.声明信号量sem_t sem1

2.初始化信号量sem_init(&sem1,0,1)

3.sem_post和sem_wait函数配合使用来达到线程同步

4.释放信号量int sem_destroy (sem_t *sem1)

它的原型为: extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value))

头文件为: #include <semaphore.h>

sem为指向信号量结构的一个指针;

pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;

value给出了信号量的初始值。

函数sem_post( sem_t *sem )用来增加信号量的值当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。

函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。

函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。

函数sem_destroy(sem_t *sem)用来释放信号量sem。

这个问题需要的知识主要包括:

1 多进程间进行通信;

2 使用同步信号量(semaphore)和互斥信号量(mutex)进行数据保护。

参考代码如下,可以参照注释辅助理解:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

#include <semaphore.h>

#define N 2   // 消费者或者生产者的数目

#define M 10 // 缓冲数目

int in = 0   // 生产者放置产品的位置

int out = 0 // 消费者取产品的位置

int buff[M] = {0} // 缓冲初始化为0, 开始时没有产品

sem_t empty_sem // 同步信号量, 当满了时阻止生产者放产品

sem_t full_sem   // 同步信号量, 当没产品时阻止消费者消费

pthread_mutex_t mutex // 互斥信号量, 一次只有一个线程访问缓冲

int product_id = 0   //生产者id

int prochase_id = 0 //消费者id

/* 打印缓冲情况 */

void print()

{

int i

for(i = 0 i < M i++)

   printf("%d ", buff[i])

printf("\n")

}

/* 生产者方法 */ 

void *product()

{

int id = ++product_id

while(1)

{

   // 用sleep的数量可以调节生产和消费的速度,便于观察

   sleep(1)

   //sleep(1)

  

   sem_wait(&empty_sem)

   pthread_mutex_lock(&mutex)

  

   in = in % M

   printf("product%d in %d. like: \t", id, in)

  

   buff[in] = 1  

   print()  

   ++in

  

   pthread_mutex_unlock(&mutex)

   sem_post(&full_sem)  

}

}

/* 消费者方法 */

void *prochase()

{

int id = ++prochase_id

while(1)

{

   // 用sleep的数量可以调节生产和消费的速度,便于观察

   sleep(1)

//sleep(1)

  

   sem_wait(&full_sem)

   pthread_mutex_lock(&mutex)

  

   out = out % M

   printf("prochase%d in %d. like: \t", id, out)

  

   buff[out] = 0

   print()

   ++out

  

   pthread_mutex_unlock(&mutex)

   sem_post(&empty_sem)

}

}

int main()

{

pthread_t id1[N]

pthread_t id2[N]

int i

int ret[N]

// 初始化同步信号量

int ini1 = sem_init(&empty_sem, 0, M) 

int ini2 = sem_init(&full_sem, 0, 0)  

if(ini1 && ini2 != 0)

{

   printf("sem init failed \n")

   exit(1)

//初始化互斥信号量 

int ini3 = pthread_mutex_init(&mutex, NULL)

if(ini3 != 0)

{

   printf("mutex init failed \n")

   exit(1)

// 创建N个生产者线程

for(i = 0 i < N i++)

{

   ret[i] = pthread_create(&id1[i], NULL, product, (void *)(&i))

   if(ret[i] != 0)

   {

    printf("product%d creation failed \n", i)

    exit(1)

   }

}

//创建N个消费者线程

for(i = 0 i < N i++)

{

   ret[i] = pthread_create(&id2[i], NULL, prochase, NULL)

   if(ret[i] != 0)

   {

    printf("prochase%d creation failed \n", i)

    exit(1)

   }

}

//销毁线程

for(i = 0 i < N i++)

{

   pthread_join(id1[i],NULL)

   pthread_join(id2[i],NULL)

}

exit(0) 

}

在Linux下编译的时候,要在编译命令中加入选项-lpthread以包含多线程支持。比如存储的C文件为demo.c,要生成的可执行文件为demo。可以使用命令:

gcc demo.c -o demo -lpthread

程序中为便于观察,使用了sleep(1)来暂停运行,所以查看输出的时候可以看到,输出是每秒打印一次的。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/443313.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-30
下一篇2023-05-30

发表评论

登录后才能评论

评论列表(0条)

    保存