在前面的文章中提及到,一个进程中的多个线程是共享同一段资源的,由于线程对资源的竞争引出了锁。其中mutex是一种简单的加锁方法,这个互斥锁只有两种状态,那就是上锁和解锁,可以把互斥锁看作是某种意义上的全局变量。在某一时刻,只能有一个线程取得这个互斥上的锁,拥有上锁状态的线程可以对共享资源进行操作,而其他线程在该线程未解锁之前,够会被挂起,直到上锁的线程解开锁。可以这么说,互斥锁使得共享资源按序的在各个线程上操作。

互斥锁的操作主要包括互斥锁初始化、上锁、判断上锁、解锁、摧毁互斥锁。其中互斥锁可以分为快速互斥锁、递归互斥锁这检错互斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要等待挂起。快速锁是指调用线程会阻塞直到线程锁得到解锁为止。递归锁能够成功地返回并且增加调用线程在互斥上的加锁次数,比如一个链表在进行插入的操作时,可以进行查找的操作。检错锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误的信息。

1、函数简义。

(1)pthread_mutex_init

头文件:                  <pthread.h>

函数原型:               int pthread_mutex_init (pthread_mutex_t* mutex,

const pthread_mutexattr_t* mutexattr);

函数传入值:            mutex:互斥锁。

mutexattr:PTHREAD_MUTEX_INITIALIZER:创建快速互斥锁。

PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP:创建递归互斥锁。

PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP:创建检错互斥锁。

函数返回值:            成功:0

出错:-1

(2)上锁函数:

int pthread_mutex_lock(pthread_mutex_t* mutex);

int pthread_mutex_trylock (pthread_mutex_t* mutex);

int pthread_mutex_unlock (pthread_mutex_t* mutex);

int pthread_mutex_destroy (pthread_mutex_t* mutex);

函数传入值:            mutex:互斥锁。

函数返回值:            同上。

2、互斥锁实现。

[cpp] view plaincopy
  1. include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <errno.h>
  5. #include <unistd.h>
  6. #define  return_if_fail(p)  /
  7. if((p) == 0){printf("[%s]:func error!/n",__func__);return;}
  8. typedef struct _PrivInfo
  9. {
  10. pthread_mutex_t mutex;
  11. int lock_var;
  12. time_t end_time;
  13. }PrivInfo;
  14. static void info_init (PrivInfo* thiz);
  15. static void* pthread_func_1 (PrivInfo* thiz);
  16. static void* pthread_func_2 (PrivInfo* thiz);
  17. int main (int argc, char** argv)
  18. {
  19. pthread_t pt_1 = 0;
  20. pthread_t pt_2 = 0;
  21. int ret = 0;
  22. PrivInfo* thiz = NULL;
  23. thiz = (PrivInfo*)malloc (sizeof (PrivInfo));
  24. if (thiz == NULL)
  25. {
  26. return -1;
  27. }
  28. info_init(thiz);
  29. ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);
  30. if (ret != 0)
  31. {
  32. perror ("pthread_1_create:");
  33. }
  34. ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);
  35. {
  36. perror ("pthread_2_create:");
  37. }
  38. pthread_join (pt_1, NULL);
  39. pthread_join (pt_2, NULL);
  40. pthread_mutex_destroy (&thiz->mutex);
  41. free (thiz);
  42. thiz = NULL;
  43. return 0;
  44. }
  45. static void info_init (PrivInfo* thiz)
  46. {
  47. return_if_fail (thiz != NULL);
  48. thiz->lock_var = 0;
  49. thiz->end_time = time (NULL) + 10;
  50. pthread_mutex_init (&thiz->mutex, NULL);
  51. return;
  52. }
  53. static void* pthread_func_1 (PrivInfo* thiz)
  54. {
  55. return_if_fail (thiz != NULL);
  56. int i = 0;
  57. int ret = 0;
  58. while (time (NULL) < thiz->end_time)
  59. {
  60. ret  = pthread_mutex_lock (&thiz->mutex);
  61. if (ret != 0)
  62. {
  63. perror ("[%s]pthread_mutex_lock");
  64. }
  65. else
  66. {
  67. printf ("pthread1:pthread1 lock the variable!/n");
  68. }
  69. for (i = 0; i < 2; i++)
  70. {
  71. sleep (1);
  72. thiz->lock_var ++;
  73. }
  74. ret = pthread_mutex_unlock (&thiz->mutex);
  75. if (ret != 0)
  76. {
  77. perror ("[%s]pthread_mutex_unlock");
  78. }
  79. else
  80. {
  81. printf ("pthread1: pthread1 unlock the variable./n");
  82. }
  83. }
  84. return;
  85. }
  86. static void* pthread_func_2 (PrivInfo* thiz)
  87. {
  88. return_if_fail (thiz != NULL);
  89. int ret = 0;
  90. while (time (NULL) < thiz->end_time)
  91. {
  92. ret = pthread_mutex_trylock (&thiz->mutex);
  93. if (ret == EBUSY)
  94. {
  95. printf ("pthread2:the variable is locked by thread1./n");
  96. }
  97. else
  98. {
  99. if (ret != 0)
  100. {
  101. perror ("[%s]pthread2_mutex_trylock");
  102. }
  103. else
  104. {
  105. printf ("pthread2: pthread2 lock the variable./n");
  106. }
  107. ret = pthread_mutex_unlock (&thiz->mutex);
  108. if (ret != 0)
  109. {
  110. perror ("[%s]pthread_mutex_lock");
  111. }
  112. sleep (3);
  113. }
  114. }
  115. }

在上例的中,是对变量lock_var的读写进行加锁,线程一是对其进行写,在写的时候,线程二不能对其进行读。直到线程一解锁,线程二得到互斥锁,才能进行读。同样,在线程二进行读的时候,线程一不能进行写。

今天讲述到这里,下一篇文章将讲述怎样通过信号量来达到互斥锁的效果。

linux多线程学习(四)——互斥锁线程控制相关推荐

  1. 艾伟:C#多线程学习(六) 互斥对象

    本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...

  2. C#多线程学习(六) 互斥对象

    C#多线程学习(六) 互斥对象 原文链接:http://kb.cnblogs.com/page/42533/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个 ...

  3. C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  4. linux多线程学习(五)——信号量线程控制

    在上一篇文章中,讲述了线程中互斥锁的使用,达到对共享资源互斥使用.除了使用互斥锁,信号量,也就是操作系统中所提到的PV原语,能达到互斥和同步的效果,这就是今天我们所要讲述的信号量线程控制. PV原语是 ...

  5. Linux与Shell学习--shell系列11--流程控制4(until循环)

    until循环和while循环整体概念是一样的,只不过while循环的循环前提是满足while判断时进入子模块中,当不满足while判断条件时跳出循环,如果while判断条件一直满足就一直进行循环:u ...

  6. C#多线程学习6——互斥对象

    如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先 ...

  7. Linux 多线程同步机制:互斥量、信号量、条件变量

    互斥量:互斥量提供对共享资源的保护访问,它的两种状态:lock和unlock,用来保证某段时间内只有一个线程使用共享资源,互斥量的数据类型是pthread_mutex_t 主要涉及函数:pthread ...

  8. day 34 守护线程守护进程 互斥锁线程 信号量 生产者消费者

    今日内容 1.守护进程vs 守护线程(*) 2.互斥锁(**) 3.信号量(**) 4.生产者消费者模型(*****) 5.GIL(什么时候用进程,什么时候用线程)(*****) 一.守护进程和守护线 ...

  9. linux多线程编程之互斥锁

    多线程并行运行,共享同一种互斥资源时,需要上互斥锁来运行,主要是用到pthread_mutex_lock函数和pthread_mutex_unlock函数对线程进行上锁和解锁 下面是一个例子: #in ...

最新文章

  1. 32位 shell.efi x86_通过grub,让32位的efi也能运行64位的Linux发行版
  2. python的用途实例-python进程池作用展示及实例解析
  3. ML之nyoka:基于nyoka库利用LGBMClassifier模型实现对iris数据集训练、保存为pmml模型并重新载入pmml模型进而实现推理
  4. Ubuntu常用终端快捷键
  5. 细说ReactiveCocoa的冷信号与热信号(一)
  6. ios 消息服务器,关于IOS APNS推送消息(iphone端+服务端)
  7. 哈希表数据结构_算法与数据结构-哈希表
  8. 用EL表达式显示客户端使用的浏览器
  9. 检测同心圆_两“心”携手,共抗心衰——“同心圆”心衰俱乐部走进临安图书馆~...
  10. 【用电量预测】基于matlab SVM用电量预测【含Matlab源码 103期】
  11. 计算机使用快捷键大全
  12. 关于protel 99se 汉化后某些菜单消失的解决方法
  13. C语言实现通讯录管理系统(动态内存分配版)
  14. 荐书:「时差党」——出国留学不是一件容易的事
  15. 【python】错误SyntaxError: invalid syntax的解决方法总结
  16. Android ToolBar修改返回按钮图标
  17. Python双目相机计算三维坐标(使用opencv自带图片)
  18. 计算机联锁系统工程设计论文,计算机联锁控制系统论文
  19. 五金配件批发行业在线订单管理系统解决方案
  20. GCC-PHAT算法

热门文章

  1. strtus中action注入spring bean
  2. tt公路车Java配置怎么样_普通公路车换TT车把可以吗,别的东西还有需要换的吗?...
  3. HuggingFace学习1:tokenizer学习与将文本编码为固定长度(pytorch)
  4. git 小乌龟 配置_Git-Bash和TortoiseGit小乌龟客户端配置记录
  5. 关于php的函数,总结关于PHP文件函数有哪些
  6. 鸿蒙系统和你,鸿蒙系统面世,但与您所想的不一样
  7. LeetCode 38. Count and Say
  8. 高性能MYSQL读书笔记1
  9. 4.JAVA之GUI编程事件监听机制
  10. 如何让我们的VMware虚拟机上网——转载