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


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

    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. }

  • 相关阅读:
    uniapp获取接口数据并渲染至页面中
    时间复杂度
    webpack 中 require.context() 的用法
    思考(八十九):WAL 实现
    小程序WebView远程连接报错(1202)网络出错,轻触屏幕重新加载,如何解决这个问题?
    R语言dplyr包filter函数过滤dataframe数据中指定数据列的内容包含指定字符串的数据行、基于grepl函数
    大模型概念解析 | Prompt Engineering
    IO和进程day06(线程续、同步线程互斥)
    我服了!SpringBoot升级后这服务我一个星期都没跑起来!(上)
    C-V2X(CANoe)CAPL接收CAN消息
  • 原文地址:https://blog.csdn.net/l_ethan/article/details/126019087