• 多线程打印 - 互斥量的使用


    题目要求

    在任务一的基础上进一步,如果我们不想 A 和 B 的行交替出现,即无论该程序运行多少次都是先连续打印三行 A 再连续打印三行 B,或者反之,连续打印三行 B 再连续打印三行 A也可以,该如何实现?(提示,使用 mutex

    相关知识:

    l 临界资源:首先谈一下临界资源的概念:某些资源来说,其在同一时间只能被一段机器指令序列所占用。这些一次只能被一段指令序列所占用的资源就是所谓的临界资源。典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程/线程所共享的一些变量和数据等。这类资源如果不被看成临界资源加以保护,那么很有可能因为访问冲突造成数据错乱的问题。

    l 临界区:对于临界资源的访问,必须是互斥进行。也就是当临界资源被一个指令序列占用时,另一个需要访问相同临界资源的指令序列就不能被执行。我们知道这里所说的指令序列在现实中就都是作为进程/线程的一部分被OS调度执行的,指令序列不能执行的实际意思就是我们所说的其所在的进程/线程会被阻塞,直到其所申请的临界资源被释放。而程序内访问临界资源的代码序列被称为临界区。

    l 互斥:是指同时只允许一个访问者对临界资源进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

    l 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

    Linux上对线程互斥和同步的支持方法。

    互斥

    同步

    进程

    System V信号量

    POSIX 信号量

    线程锁共享

    System V信号量(常用于进程的同步,还不清楚是否可以用于线程

    POSIX 信号量

    线程

    pthread_mutex_t

    POSIX 信号量

    pthread_cond_t

    POSIX 信号量

    1. 线程库互斥量的使用

    函数

    说明

    int  pthread_mutex_init

    (pthread_mutex_t  *mutex,

    pthread_mutexattr_t *attr)  

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    1. 静态初始化可以通过PTHREAD_MUTEX_INITIALIZER宏

    pthread_mutex_t A = PTHREAD_MUTEX_INITIALIZER;

    1. 动态初始化可以通过pthread_mutex_init函数进行,一般在通过pthread_mutex_init初始化的锁,在不需要时应调用pthread_mutex_destroy销毁。

    attr:  互斥锁属性  //  NULL表示缺省属性

    int  pthread_mutex_lock(pthread_mutex_t *mutex)

    通过pthread_mutex_lock来获得锁

    注意: 如果想获得的锁已经被别的线程获取了,此时pthread_mutex_lock将引起调用者阻塞

    int  pthread_mutex_unlock(pthread_mutex_t *mutex)

    通过pthread_mutex_unlock来释放获得的锁

    审核要求:

    1. 提交全部程序代码,代码思路规范清晰,命名规范。

    2. 运行能直接输出所要求的结果。

    1. #include
    2. #include
    3. pthread_mutex_t mtx;
    4. void *funa(void *arg)
    5. {
    6. if(0!=pthread_mutex_lock(&mtx))
    7. {
    8. perror("perror_mutex_lock");
    9. exit(0);
    10. }
    11. int i;
    12. for(i=0;i<3;i++)
    13. {
    14. sleep(1);
    15. printf("AAAAAAAAAA\n");
    16. }
    17. if(0!=pthread_mutex_unlock(&mtx))
    18. {
    19. perror("perror_mutex_lock");
    20. exit(0);
    21. }
    22. pthread_exit(NULL);
    23. }
    24. void *funb(void *arg)
    25. {
    26. if(0!=pthread_mutex_lock(&mtx))
    27. {
    28. perror("perror_mutex_lock");
    29. exit(0);
    30. }
    31. int i;
    32. for(i=0;i<3;i++)
    33. {
    34. sleep(1);
    35. printf("BBBBBBBBBB\n");
    36. }
    37. if(0!=pthread_mutex_unlock(&mtx))
    38. {
    39. perror("perror_mutex_lock");
    40. exit(0);
    41. }
    42. pthread_exit(NULL);
    43. }
    44. int main()
    45. {
    46. pthread_t ta,tb;
    47. if(0!=pthread_mutex_init(&mtx,NULL))
    48. {
    49. perror("pthread_mutex_init");
    50. exit(0);
    51. }
    52. if(0!=pthread_create(&ta,NULL,funa,NULL))
    53. {
    54. perror("pthread error!");
    55. exit(0);
    56. }
    57. if(0!=pthread_create(&tb,NULL,funb,NULL))
    58. {
    59. perror("pthread error!");
    60. exit(0);
    61. }
    62. if(0!=pthread_join(ta,NULL))
    63. {
    64. perror("join error\n");
    65. exit(0);
    66. }
    67. if(0!=pthread_join(tb,NULL))
    68. {
    69. perror("join error\n");
    70. exit(0);
    71. }
    72. if(0!=pthread_mutex_destroy(&mtx))
    73. {
    74. perror("pthread_mutex_destroy");
    75. exit(0);
    76. }
    77. return 0;
    78. }

  • 相关阅读:
    getid3 获取视频时长
    中标麒麟国产服务器安装MinIO报错不能读取该二进制文件解决方案
    字节9.3秋招研发笔试 【后端方向】第三题
    升级 MacOS 系统后,playCover 内游戏打不开了如何解决
    Centos7配置国内yum源
    Vue3.x使用vuex进行页面间通信
    LeetCode_位运算_困难_805.数组的均值分割
    MySQL数据库创建用户并授权查询某个表
    D. Decrease the Sum of Digits
    pyqt5 学习笔记六(QFormLayout)表单布局器
  • 原文地址:https://blog.csdn.net/L6666688888/article/details/128075728