互斥量(Mutex)是“mutual exclusion”的缩写。互斥量是实现线程同步,和保护同时写共享数据的主要方法。
  互斥量对共享数据的保护就像一把锁。在Pthreads中,任何时候仅有一个线程可以锁定互斥量,因此,当多个线程尝试去锁定该互斥量时仅有一个会成功。直到锁定互斥量的线程解锁互斥量后,其他线程才可以去锁定互斥量。线程必须轮着访问受保护数据。
  一个拥有互斥量的线程经常用于更新全局变量。确保了多个线程更新同样的变量以安全的方式运行,最终的结果和一个线程处理的结果是相同的。这个更新的变量属于一个“临界区(critical section)”。

  使用互斥量的典型顺序如下:

  • 创建和初始一个互斥量
  • 多个线程尝试去锁定该互斥量
  • 仅有一个线程可以成功锁定改互斥量
  • 锁定成功的线程做一些处理
  • 线程解锁该互斥量
  • 另外一个线程获得互斥量,重复上述过程
  • 最后销毁互斥量

  当多个线程竞争同一个互斥量时,失败的线程会阻塞在lock调用处。可以用“trylock”替换“lock”,则失败时不会阻塞。当保护共享数据时,程序员有责任去确认是否需要使用互斥量。如,若四个线程会更新同样的数据,但仅有一个线程用了互斥量,则数据可能会损坏。

创建和销毁互斥量:

pthread_mutex_init (mutex,attr)
pthread_mutex_destroy (mutex)
pthread_mutexattr_init (attr)
pthread_mutexattr_destroy (attr)

用法

互斥量必须用类型pthread_mutex_t类型声明,在使用前必须初始化,这里有两种方法可以初始化互斥量:
声明时静态地,如: pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
动态地用pthread_mutex_init()函数,这种方法允许设定互斥量的属性对象attr。
互斥量初始化后是解锁的。
attr对象用于设置互斥量对象的属性,使用时必须声明为pthread_mutext_attr_t类型,默认值可以是NULL。Pthreads标准定义了三种可选的互斥量属性:

  • 协议(Protocol): 指定了协议用于阻止互斥量的优先级改变
  • 优先级上限(Prioceiling):指定互斥量的优先级上限
  • 进程共享(Process-shared):指定进程共享互斥量

注意所有实现都提供了这三个可先的互斥量属性。
pthread_mutexattr_init()和pthread_mutexattr_destroy()函数分别用于创建和销毁互斥量属性对象。
pthread_mutex_destroy()应该用于释放不需要再使用的互斥量对象。

锁定和解锁互斥量:

函数

pthread_mutex_lock (mutex)
pthread_mutex_trylock (mutex)
pthread_mutex_unlock (mutex)

用法

线程用pthread_mutex_lock()函数去锁定指定的mutex变量,若该mutex已经被另外一个线程锁定了,该调用将会阻塞线程直到mutex被解锁。
pthread_mutex_trylock() will attempt to lock a mutex. However, if the mutex is already locked, the routine will return immediately with a "busy" error code. This routine may be useful in pthread_mutex_trylock().

  尝试着去锁定一个互斥量,然而,若互斥量已被锁定,程序会立刻返回并返回一个忙错误值。该函数在优先级改变情况下阻止死锁是非常有用的。线程可以用pthread_mutex_unlock()解锁自己占用的互斥量。在一个线程完成对保护数据的使用,而其它线程要获得互斥量在保护数据上工作时,可以调用该函数。若有一下情形则会发生错误:

  • 互斥量已经被解锁
  • 互斥量被另一个线程占用

互斥量并没有多么“神奇”的,实际上,它们就是参与的线程的“君子约定”。写代码时要确信正确地锁定,解锁互斥量。
Q:有多个线程等待同一个锁定的互斥量,当互斥量被解锁后,那个线程会第一个锁定互斥量?
A:除非线程使用了优先级调度机制,否则,线程会被系统调度器去分配,那个线程会第一个锁定互斥量是随机的。

用例: 

 #include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h> typedef struct ct_sum
{
int sum;
pthread_mutex_t lock;
}ct_sum; void * add1(void *cnt)
{
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
for(int i=; i < ; i++)
{
(*(ct_sum*)cnt).sum += i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return ;
}
void * add2(void *cnt)
{
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
for(int i=; i<; i++)
{
(*(ct_sum*)cnt).sum += i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return ;
} int main(void)
{
pthread_t ptid1, ptid2;
ct_sum cnt;
pthread_mutex_init(&(cnt.lock), NULL);
cnt.sum=; pthread_create(&ptid1, NULL, add1, &cnt);
pthread_create(&ptid2, NULL, add2, &cnt); pthread_join(ptid1,NULL);
pthread_join(ptid2,NULL); printf("sum %d\n", cnt.sum);
pthread_mutex_destroy(&(cnt.lock)); return ;
}

pThreads线程(二) 线程同步--互斥量/锁的更多相关文章

  1. 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  2. (转)经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  3. 多线程面试题系列(7):经典线程同步 互斥量Mutex

    前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  4. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...

  5. 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  6. CreateThread创建线程 互斥量锁

    HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD:线程安全相关的属性,常置为NULL SIZE_T dwStackS ...

  7. windows多线程同步--互斥量

    关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  8. C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

  9. 第二十篇 .NET高级技术之C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

随机推荐

  1. NOIP2015其余几道题

    T1: #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> # ...

  2. BZOJ2278 : [Poi2011]Garbage

    如果两个环相交,那么相交的部分相当于没走. 因此一定存在一种方案,使得里面的环都不相交. 把不需要改变状态的边都去掉,剩下的图若存在奇点则无解. 否则,每找到一个环就将环上的边都删掉,时间复杂度$O( ...

  3. Codeforces Beta Round #14 (Div. 2) A. Letter 水题

    A. Letter 题目连接: http://www.codeforces.com/contest/14/problem/A Description A boy Bob likes to draw. ...

  4. Slickflow.NET 开源工作流引擎基础介绍(九) -- .NET Core2.0 版本实现介绍

    前言:.NET Core 是.NET Framework的新一代版本,是微软开发的第一个跨平台 (Windows.Mac OSX.Linux) 的应用程序开发框架(Application Framew ...

  5. C# 读带复选框的excel,写excel并设置字体、边框、背景色

    这是一篇excel读写功能大汇总,通过C#调用Microsoft.Office.Interop.Excel.dll才能完成任何复杂格式excel的读写操作. 本文需要读取的excel格式如下: 可见表 ...

  6. ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32

    /* ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio Licensed under the Apache License, Version 2 ...

  7. 谨慎注意WebBrowser控件的DocumentCompleted事件

    引言 WebBrowser控件的DocumentCompleted事件一般就被认定为是在页面完全加载完毕后产生,而注释中也是这么写的: 但事实却并非如此. 首先它不一定会在完全加载完毕时才触发,有时就 ...

  8. Java 微服务实践 - Spring Boot 系列

    https://segmentfault.com/l/1500000009515571

  9. Apache Kafka —一个不同的消息系统

    Apache已经发布了Kafka 0.8,也是自从成为Apache软件基金会的顶级项目后Kafka的 第一个主版本. Apache Kafka是发布—订阅消息传递,实现了分布式提交日志,适用于离线和在 ...

  10. bash 脚本中分号的作用

    在Linux bash shell中,语句中的分号一般用作代码块标识 1.单行语句一般要用到分号来区分代码块.比如: weblogic@pmtest:/$if [ "$PS1" ] ...