zoukankan      html  css  js  c++  java
  • Linux下进程的同步相互排斥实例——生产者消费者

    linux下的同步和相互排斥

    Linux sync_mutex


    看的更舒服点的版本号= =

    https://github.com/Svtter/MyBlog/blob/master/Linux/pthread/Linux_producer_consumer.md


    Semaphore.h

    一份好文档,胜读十年书

    本文參考了诸多资料,百度百科。cplusplus等

    首先介绍一个头文件
    #include <semaphore.h>

    这里面包括了大多数的所须要使用的信号量.
    包括:

    • int sem_init(sem_t *sem, int pshared, unsigned int value)
      用于初始化信号量。
      value代表信号量的初始值,
      pshare代表信号量是进程内的线程共享。还是进程间共享。

    对于Linux而言,就是子进程共享和父进程共享——Linux中不存在线程的问题。Linux中的线程。进程均为进程。仅仅是看进程组。子进程父进程而已。对于进程关系。能够使用pstree查看。

    返回0时成功。返回-1时失败。而且设置errno
    使用perror输出错误信息:
    - EINVAL
    value 超过 `SEM_VALUE_MAX`
    - ENOSYS
    pshared 非零。但系统还没有支持进程共享的信号量。
    


    • int sem_post(sem_t *sem)
      这个函数相当于V操作,是一个"原子操作"——即是不会被打断(中断)的。

      并行计算中会出现的两个线
      程同一时候对一个变量相加导致变量的值仅产生了一次变化在此处是不成立的。
      返回0时成功,返回-1时失败, 而且设置errno:

      • EINVAL
        sem 不是一个有效的信号量。
      • EOVERFLOW
        信号量同意的最大值将要被超过。

    • int sem_wait(sem_t *sem)
      这个函数相当于P操作,也是一个"原子操作"。

      等待对变量-1,假设不能对变量-1,则进入等待队列

    • int sem_trywait(sem_t *sem)
      假设变量不能-1(即sem_t为0),则不会进入等待队列,直接返回错误代码。
    • int sem_timedwait(sem_t *sem)
    • int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
      • return 0 (success), return -1 (failure) and set errno:
        • EINTR
          The call was interrupted by a signal handler; see signal(7).
          //调用被信号处理中断
        • EINVAL sem is not a valid semaphore.
            //sem不是有效的信号量
          The following additional error can occur for sem_trywait():
            //以下的错误是sem_trywait()可能发生的:
        • EAGAIN The operation could not be performed without blocking (i.e., the
            semaphore currently has the value zero).
            //除了锁定无法进行别的操作(如信号量当前是0值).
          The following additional errors can occur for sem_timedwait():
            //以下的错误是sem_timedwait()可能发生的:
        • EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than or
            equal to 1000 million.
            //abs_timeout.tv_nsecs 的值比0小或者大于等于1000毫秒(译者注:纳秒的值不能比0小,不能比1秒大)
        • ETIMEDOUT
            The call timed out before the semaphore could be locked.
            //在信号量锁定之前就超时了
        • 注意
          对这些函数,信号处理程序总是会中断堵塞,无论是否使用了sigaction(2)的SA_RESTART标志位.

    1. /*=============================================================================
    2. #
    3. # Author: svtter - svtter@qq.com
    4. #
    5. # QQ : 57180160
    6. #
    7. # Last modified: 2014-10-03 20:35
    8. #
    9. # Filename: producer_consumer.cc
    10. #
    11. # Description:
    12. #
    13. =============================================================================*/
    14. #include <cstdio>
    15. #include <unistd.h>
    16. #include <semaphore.h>
    17. #include <pthread.h>
    18. #include <sys/types.h>
    19. #include <stdlib.h>
    20. #include <iostream>
    21. using namespace std;
    22. #define N 5
    23. #define item int
    24. // P/V操作
    25. void P(sem_t* sem)
    26. {
    27. if(sem_wait(sem))
    28. perror("P error!");
    29. }
    30. void V(sem_t* sem)
    31. {
    32. if(sem_post(sem))
    33. perror("V error!");
    34. }
    35. sem_t mutex;
    36. sem_t full;
    37. sem_t empty;
    38. item buffer[N];
    39. int i = 0, j = -1;
    40. void init_sem()
    41. {
    42. sem_init(&mutex, 0, 1);
    43. sem_init(&full, 0, 0);
    44. sem_init(&empty, 0, N);
    45. }
    46. void* producer(void *arg)
    47. {
    48. int product;
    49. while(1)
    50. {
    51. //生成随机数字
    52. product = rand()%100;
    53. // cout << "producer running..." << endl;
    54. P(&empty);
    55. P(&mutex);
    56. buffer[i] = product;
    57. printf("producer produced %d @ %d pos ",
    58. product, i);
    59. i=(i+1)%N;
    60. V(&mutex);
    61. V(&full);
    62. sleep(1);
    63. }
    64. }
    65. void* consumer(void *arg)
    66. {
    67. int product, temp;
    68. while(1)
    69. {
    70. // cout << "consumer running..." << endl;
    71. P(&full);
    72. P(&mutex);
    73. j = (j+1)%N;
    74. product = buffer[j];
    75. V(&mutex);
    76. V(&empty);
    77. printf("Consumer consumed %d @ %d pos ",
    78. product, j);
    79. sleep(3);
    80. }
    81. }
    82. int main()
    83. {
    84. //random num
    85. srand(time(NULL));
    86. init_sem();
    87. int error;
    88. pthread_t producer_t, consumer_t;
    89. error = pthread_create(&producer_t, NULL, producer, NULL);
    90. if(error != 0)
    91. printf("error in create producer. ");
    92. else
    93. printf("create producer success! ");
    94. pthread_create(&consumer_t, NULL, consumer, NULL);
    95. if(error != 0)
    96. printf("error in create consumer. ");
    97. else
    98. printf("create consumer success! ");
    99. pthread_join(producer_t, NULL);
    100. pthread_join(consumer_t, NULL);
    101. return 0;
    102. }
  • 相关阅读:
    Java版远程控制V1.0
    Struts2使用Kindeditor4.0.3在线编辑器上传图片、视频、FLASH、附件
    给你的网站加上站内搜索Spring+Hibernate基于Compass(基于Lucene)实现
    Hibernate整合进spring使用自己的事务处理
    Hibernate整合进spring使用hibernateTemplate.getSessionFactory().getCurrentSession()理解
    GWT(Google Web Toolkit)入门学习
    转载:狼与哈士奇
    [转]远程桌面无法连接上(管理员已结束了会话)的解决方法
    ibmDW:凤凰涅槃:从 iBatis 到 MyBatis
    hibernate多对多映射拆成2个一对多映射(注解)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5362869.html
Copyright © 2011-2022 走看看