• 20220921(信号量)


    信号量,是是相对折中的一种处理方式,既保证同步,数据不混乱,又能提高线程发送。

    由于互斥锁的粒度比较大,如果我们希望在多个线程间对某以对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降。线程从并行执行,变成了串行执行。与直接使用单进程无异。

    主要函数

    sem_init:函数(初始化信号量)

    sem_destroy:函数(销毁信号量)

    sem_wait:函数(信号量减减操作(类似加锁))

    sem_trywait:函数(尝试对信号量加锁)

    sem_timewait:函数(限时尝试对信号量加锁)

    sem_post:函数(信号量加加操作(类似解锁))

    以上6个函数的返回值都是:成功返回0,失败返回-1,同时设置(errno。(注意:他们没有pthread前缀))。

    sem_t类型,本质仍是结构体。但应用期间可简单看作为整数,忽略显示细节(类型于使用文件描述符)。

    sem_tsem:规定信号量sem不能<0,头文件

    信号量基本操作

    sem_wait:

    1.信号量大于0,则信号量--

    2.信号量等于0,再次调用会造成线程阻塞。

    sem_post:

    将信号量++,同时唤醒阻塞在信号量上的线程,由于sem的实现对用户隐藏,所以所谓的++、--操作只能通过函数来实现,而不能直接++、--符号

    信号量的初值,决定了占用信号量的线程的个数。

    一个生产者,两个消费者测试(参考下图)

     代码如下:

    1. #include <stdlib.h>
    2. #include <unistd.h>
    3. #include <pthread.h>
    4. #include <stdio.h>
    5. #include <semaphore.h>
    6. #define NUM 5
    7. int queue[NUM];//全局数组实现环形队列
    8. //用sem_t类型,定义了2个信号量变量
    9. sem_t blank_number, product_number ;//空格子信号量,产品信号量
    10. void *producer(void *arg)
    11. {
    12. sleep(10);
    13. int i=0;
    14. while (1)
    15. {
    16. sem_wait(&blank_number);//生产者将空格子数-- ,为0则阻塞等待
    17. queue[i] = rand() % 1000 + 1;//生产一个产品
    18. printf("i=%d----Produce---%d\n",i,queue[i]);
    19. sem_post(&product_number);//将产品数++
    20. i=(i+1)%NUM;//借助下标实现环形
    21. // sleep( rand()%1);
    22. sleep(1);
    23. }
    24. }
    25. void *consumer02(void *arg)
    26. {
    27. int i=1;
    28. sleep(1);
    29. while (1)
    30. {
    31. sleep(5);
    32. sem_wait(&product_number);//消费者将产品数--,为则阻塞等待
    33. printf("i=%d----Consume---%d\n" ,i, queue[i]);
    34. queue[i] = 0;//消费一个产品
    35. sem_post(&blank_number);//消费掉以后,将空格子数++
    36. i = (i+2) % NUM;
    37. // sleep(rand( )%3);
    38. }
    39. }
    40. void *consumer(void *arg)
    41. {
    42. int i=0;
    43. sleep(1);
    44. while (1)
    45. {
    46. sleep(5);
    47. sem_wait(&product_number);//消费者将产品数--,为则阻塞等待
    48. printf("i=%d----Consume---%d\n" ,i, queue[i]);
    49. queue[i] = 0;//消费一个产品
    50. sem_post(&blank_number);//消费掉以后,将空格子数++
    51. i = (i+2) % NUM;
    52. // sleep(rand( )%3);
    53. }
    54. }
    55. int main(int argc, char *argv[])
    56. {
    57. pthread_t pid, cid[2];
    58. sem_init(&blank_number, 0, NUM); //初始化线程间共享-0,空格子信号量为5
    59. sem_init(&product_number, 0,0);//初始化线程间共享-0,产品数为0
    60. pthread_create(&pid, NULL, producer, NULL);
    61. pthread_create(&cid[0], NULL, consumer, NULL);
    62. pthread_create(&cid[1], NULL, consumer02, NULL);
    63. pthread_join(pid, NULL);
    64. pthread_join(cid[0], NULL);
    65. pthread_join(cid[1], NULL);
    66. sem_destroy(&blank_number );
    67. sem_destroy(&product_number);
    68. return 0;
    69. }

  • 相关阅读:
    Java web中,服务器运行不过来
    第十六章 维护本地数据库(一)
    智能物流新纪元:分布式I/O模块重塑仓储自动化
    JUC-无锁
    开源组件搭建完整的Kubernetes-Devops平台方案
    数据化管理洞悉零售及电子商务运营——销售中的数据化管理
    Elasticsearch7.2.1 部署docker
    Docker安全及日志管理
    金仓数据库 KingbaseES 插件参考手册(23. dbms_utility)
    再获数千万元追加投资!宏景智驾B轮总融资已近「5亿元」
  • 原文地址:https://blog.csdn.net/liuasdfgqwer/article/details/126978586