• 信号量解决生产者消费者问题


    生产者消费者问题:生产者不能在容器满了继续生成,消费者不能在容器为空的时候消费

    1.信号量简介

    用户进程可以通过操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。信号量是一个变量来表示系统中某种资源的数量。

    原语:是一种特殊的程序段,其执行只能一气呵成,不可被中断。

    p、v操作

    p:

    1.s-1

    2. s-1>=0进程继续执行

    3.s-1<0,进程阻塞进入等待队列,转进程调度

    v

    1.s+1

    2.s+1>0进程继续执行

    3.s+1<=0,则从该信号的等待队列中唤醒一等待进程,然后在返回原进程继续执行或转进程调度


    2.信号量函数原型

    sem_init

     int sem_init(sem_t *sem, int pshared, unsigned int value);

    -功能:初始化信号量

    -参数:

            -sem:信号量变量的地址

            -pshared:0用在线程间,非0用在进程间

            -value:信号量中的值

    sem_destroy

    int sem_destroy(sem_t *sem);

    -功能:释放资源

    sem_wait

     int sem_wait(sem_t *sem);

    -功能:对信号量加锁,调用一次对信号量的值-1,如果值为0,就阻塞

    sem_trywait/sem_timedwait

    1. int sem_trywait(sem_t *sem);
    2. -功能:尝试对信号量加锁,调用一次对信号量的值-1,如果值为0,不阻塞
    3. int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
    4. -功能:尝试对信号量加锁,调用一次对信号量的值-1,如果值为0,等待设置的时间

    sem_post

    int sem_post(sem_t *sem);

    功能:对信号量解锁,调用一次对信号量的值+1

    3.案例源码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. //创建一个互斥量
    7. pthread_mutex_t mutex;
    8. //创建两个信号量
    9. sem_t psem;
    10. sem_t csem;
    11. struct Node{
    12. int num;
    13. struct Node *next;
    14. };
    15. struct Node *head;
    16. void *producer(void *arg){
    17. //创建新的节点,添加到链表中
    18. while(1){
    19. sem_wait(&psem);
    20. pthread_mutex_lock(&mutex);
    21. struct Node * newNode = (struct Node*)malloc(sizeof(struct Node));
    22. newNode->next=head;
    23. head=newNode;
    24. newNode->num=rand()%1000;
    25. printf("add node, num %d,tid :%ld\n",newNode->num,pthread_self());
    26. pthread_mutex_unlock(&mutex);
    27. sem_post(&csem);
    28. }
    29. }
    30. void *customer(void *arg){
    31. while(1){
    32. sem_wait(&csem);
    33. pthread_mutex_lock(&mutex);
    34. struct Node *tmp=head;
    35. head=head->next;
    36. printf("del node, num:%d,tid:%ld\n",tmp->num,pthread_self());
    37. free(tmp);
    38. pthread_mutex_unlock(&mutex);
    39. sem_post(&psem);
    40. }
    41. }
    42. //头节点
    43. struct Node * head = NULL;
    44. int main(){
    45. pthread_mutex_init(&mutex,NULL);
    46. sem_init(&psem,0,8);
    47. sem_init(&csem,0,0);
    48. //创建五个生产者线程和五个消费者线程
    49. pthread_t ptids[5],ctids[5];
    50. for(int i=0;i<5;i++){
    51. pthread_create(&ptids[i],NULL,producer,NULL);
    52. pthread_create(&ctids[i],NULL,customer,NULL);
    53. }
    54. for(int i=0;i<5;i++){
    55. pthread_detach(ptids[i]);
    56. pthread_detach(ctids[i]);
    57. }
    58. while(1){
    59. sleep(10);
    60. }
    61. pthread_mutex_destroy(&mutex);
    62. sem_destroy(&psem);
    63. sem_destroy(&csem);
    64. pthread_exit(NULL);
    65. return 0;
    66. }

  • 相关阅读:
    抗疫逆行者网页作业 感动人物HTML网页代码成品 网页作业带JS下拉菜单 最美逆行者网页模板 致敬疫情感动人物网页设计制作
    JavaScript 22 JavaScript 数字
    【css】动画彩色条纹。
    集合——Set
    【进程与线程】进程与线程 Q&A
    什么是web3.0
    【C语言刷LeetCode】56. 合并区间(M)
    【JUC系列-11】深入理解LinkedBlockingQueue的底层实现
    Java设计模式之建造者模式
    论文阅读03(基于人类偏好微调语言模型)
  • 原文地址:https://blog.csdn.net/l_ethan/article/details/126019087