许多互斥对象

如果放置了过多的互斥对象,代码就没有什么并发性可言,运行起来也比单线程解决方案慢。如果放置了过少的互斥对象,代码将出现奇怪和令人尴尬的错误。幸运的是,有一个中间立场。首先,互斥对象是用于串行化存取*共享数据*。不要对非共享数据使用互斥对象,并且,如果程序逻辑确保任何时候都只有一个线程能存取特定数据结构,那么也不要使用互斥对象。

其次,如果要使用共享数据,那么在读、写共享数据时都应使用互斥对象。用 pthread_mutex_lock() 和 pthread_mutex_unlock() 把读写部分保护起来,或者在程序中不固定的地方随机使用它们。学会从一个线程的角度来审视代码,并确保程序中每一个线程对内存的观点都是一致和合适的。为了熟悉互斥对象的用法,最初可能要花好几个小时来编写代码,但是很快就会习惯并且*也*不必多想就能够正确使用它们。


回页首

使用调用:初始化

现在该来看看使用互斥对象的各种不同方法了。让我们从初始化开始。在 thread3.c 示例 中,我们使用了静态初始化方法。这需要声明一个 pthread_mutex_t 变量,并赋给它常数 PTHREAD_MUTEX_INITIALIZER:

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

很简单吧。但是还可以动态地创建互斥对象。当代码使用 malloc() 分配一个新的互斥对象时,使用这种动态方法。此时,静态初始化方法是行不通的,并且应当使用例程 pthread_mutex_init():

int pthread_mutex_init( pthread_mutex_t *mymutex, const pthread_mutexattr_t *attr)

正如所示,pthread_mutex_init 接受一个指针作为参数以初始化为互斥对象,该指针指向一块已分配好的内存区。第二个参数,可以接受一个可选的 pthread_mutexattr_t 指针。这个结构可用来设置各种互斥对象属性。但是通常并不需要这些属性,所以正常做法是指定 NULL。

一旦使用 pthread_mutex_init() 初始化了互斥对象,就应使用 pthread_mutex_destroy() 消除它。pthread_mutex_destroy() 接受一个指向 pthread_mutext_t 的指针作为参数,并释放创建互斥对象时分配给它的任何资源。请注意, pthread_mutex_destroy() 不会 释放用来存储 pthread_mutex_t 的内存。释放自己的内存完全取决于您。还必须注意一点,pthread_mutex_init() 和 pthread_mutex_destroy() 成功时都返回零。


回页首

使用调用:锁定

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_lock() 接受一个指向互斥对象的指针作为参数以将其锁定。如果碰巧已经锁定了互斥对象,调用者将进入睡眠状态。函数返回时,将唤醒调用者(显然)并且调用者还将保留该锁。函数调用成功时返回零,失败时返回非零的错误代码。

pthread_mutex_unlock(pthread_mutex_t *mutex)

pthread_mutex_unlock() 与 pthread_mutex_lock() 相配合,它把线程已经加锁的互斥对象解锁。始终应该尽快对已加锁的互斥对象进行解锁(以提高性能)。并且绝对不要对您未保持锁的互斥对象进行解锁操作(否则,pthread_mutex_unlock() 调用将失败并带一个非零的 EPERM 返回值)。

pthread_mutex_trylock(pthread_mutex_t *mutex)

当线程正在做其它事情的时候(由于互斥对象当前是锁定的),如果希望锁定互斥对象,这个调用就相当方便。调用 pthread_mutex_trylock() 时将尝试锁定互斥对象。如果互斥对象当前处于解锁状态,那么您将获得该锁并且函数将返回零。然而,如果互斥对象已锁定,这个调用也不会阻塞。当然,它会返回非零的 EBUSY 错误值。然后可以继续做其它事情,稍后再尝试锁定。


回页首

等待条件发生

互斥对象是线程程序必需的工具,但它们并非万能的。例如,如果线程正在等待共享数据内某个条件出现,那会发生什么呢?代码可以反复对互斥对象锁定和解锁,以检查值的任何变化。同时,还要快速将互斥对象解锁,以便其它线程能够进行任何必需的更改。这是一种非常可怕的方法,因为线程需要在合理的时间范围内频繁地循环检测变化。

在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法,当线程在等待满足某些条件时使线程进入睡眠状态。一旦条件满足,还需要一种方法以唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点,线程代码将是非常高效的,并且不会占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事!

而 POSIX 条件变量将是我下一篇文章的主题,其中将说明如何正确使用条件变量。到那时,您将拥有了创建复杂线程程序所需的全部资源,那些线程程序可以模拟工作人员、装配线等等。既然您已经越来越熟悉线程,我将在下一篇文章中加快进度。这样,在下一篇文章的结尾就能放上一个相对复杂的线程程序。说到等到条件产生,下次再见!

pthread 学习系列 case2-- pthread_mutex_t的更多相关文章

  1. pthread 学习系列 case2-- 使用互斥锁

    ref http://www.ibm.com/developerworks/cn/linux/thread/posix_thread1/index.html #include <pthread. ...

  2. pthread 学习系列 case1-- 共享进程数据 VS 进程

    #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h& ...

  3. linux和android端的pthread学习

    本文起初主要想写个演示样例实測下pthread_mutex_lock和pthread_mutex_trylock差别.在linux机器上非常快就over了,可是想了一下.pthread是unix系的, ...

  4. 分布式学习系列【dubbo入门实践】

    分布式学习系列[dubbo入门实践] dubbo架构 组成部分:provider,consumer,registry,monitor: provider,consumer注册,订阅类似于消息队列的注册 ...

  5. Entity Framework Code First学习系列目录

    Entity Framework Code First学习系列说明:开发环境为Visual Studio 2010 + Entity Framework 5.0+MS SQL Server 2012, ...

  6. WCF学习系列汇总

    最近在学习WCF,打算把一整个系列的文章都”写“出来,包括理论和实践,这里的“写”是翻译,是国外的大牛写好的,我只是搬运工外加翻译.翻译的不好,大家请指正,谢谢了.如果觉得不错的话,也可以给我点赞,这 ...

  7. EF(Entity Framework)系统学习系列

    好久没写博客了,继续开启霸屏模式,好了,废话不多说,这次准备重新系统学一下EF,一个偶然的机会找到了一个学习EF的网站(http://www.entityframeworktutorial.net/) ...

  8. MVC学习系列4--@helper辅助方法和用户自定义HTML方法

    在HTML Helper,帮助类的帮助下,我们可以动态的创建HTML控件.HTML帮助类是在视图中,用来呈现HTML内容的.HTML帮助类是一个方法,它返回的是string类型的值. HTML帮助类, ...

  9. YYKit学习系列 ---- 开篇

    准备花半年时间系统学习YYKit,  学习过程会放入"YYKit学习系列"这个分类, 喜欢YYKit的可以随时留意我的文章, 一起学习!!!

随机推荐

  1. [CareerCup] 1.8 String Rotation 字符串的旋转

    1.8 Assume you have a method isSubstring which checks if one word is a substring of another. Given t ...

  2. Convert和Parse对null值处理的区别

    类型的转换在日常的变成中是经常被用到的,我们最常用的类型转换的方法就是Convert和Parse, 下面来说一下这两者null值处理的区别. int i1 = Convert.ToInt32(null ...

  3. 对于AP中为什么有4个WEP KEY的分析

    这篇文章简要分析一下为什么有4个WEP KEY,及其中的一些原因. SPEC 用过AP的都知道,AP中有4个WEP KEY,但是为什么要设置4个呢,这个是WEP帧的格式决定的: 图中的keyid是2个 ...

  4. JavaScript实例-----反选

    <!DOCTYPE HTML> <html> <head> <script> function myFunction() { var oTab = do ...

  5. 喝咖啡写脚本,顺便再加一点点CSS语法糖 2.五分钟学会Less

    CoffeeScript + Html5 + Less这个新组合,看上去Less更容易拿下,先尝尝糖吧. Less这么小个东西,竟然要FQ,真是没有天理,简直不可理喻,先不管那么多了,那就看这个吧.h ...

  6. Xamarin.Forms——尺寸大小(五 Dealing with sizes)

    如之前所见的大量可视化元素均有自己的尺寸大小: iOS的状态栏高度为20,所以我们需要调整iOS的页面的Padding值,留出这个高度. BoxView设置它的默认宽度和高度为40. Frame的默认 ...

  7. html之给文本框设置宽度和高度/input的无边框效果

    <input name="" type="text" style="width:200px; height:20px;" /> ...

  8. nginx 下 location 配置解释

    当我们在使用负载均衡和反向代理的时候 我们会考到虚拟主机下面有着个配置 现在我们看一下反向代理的location 下面的配置实例: server { listen 80 ;    监听的端口号 ser ...

  9. css中的默认margin

    上班打酱油中,你懂的; body的margin为8px; webkit默认行高18px:height18px; 默认font-size16px p默认margin是16px 0 16px 0; ul和 ...

  10. nodeJs抓取网页

    var fs = require('fs'); var jquery = require('jquery'); var url = require('url'); var data = { 0 : ' ...