Linux下为了多线程同步,通常用到锁的概念。
posix下抽象了一个锁类型的结构:ptread_mutex_t。通过对该结构的操作,来判断资源是否可以访问。顾名思义,加锁(lock)后,别人就无法打开,只有当锁没有关闭(unlock)的时候才能访问资源。

即对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。

  要更改缺省的互斥锁属性,可以对属性对象进行声明和初始化。通常,互斥锁属性会设置在应用程序开头的某个位置,以便可以快速查找和轻松修改。

1.函数原型:

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);

该函数用于C函数的多线程编程中,互斥锁的初始化。

  pthread_mutex_init()函数是以动态方式创建互斥锁的,参数attr指定了新建互斥锁的属性。如果参数attr为NULL,则使用默认的互斥锁属性,默认属性为快速互斥锁 。互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。

  pthread_mutexattr_init()函数成功完成之后会返回零,其他任何返回值都表示出现了错误。

  函数成功执行后,互斥锁被初始化为锁住态。

 2. 互斥锁属性

互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前(glibc2.2.3,linuxthreads0.9)有四个值可供选择:

  * PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。

  * PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。

  * PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

  * PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

3. 其他锁操作

  锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。对于普通锁和适应锁类型,解锁者可以是同进程内任何线程;而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由加锁者解锁,但实验结果表明并没有这种限制,这个不同目前还没有得到解释。在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。

int pthread_mutex_lock(pthread_mutex_t *mutex)

  int pthread_mutex_unlock(pthread_mutex_t *mutex)

  int pthread_mutex_trylock(pthread_mutex_t *mutex)

  pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。

4. 死锁:

  死锁主要发生在有多个依赖锁存在时, 会在一个线程试图以与另一个线程相反顺序锁住互斥量时发生. 如何避免死锁是使用互斥量应该格外注意的东西。

  总体来讲, 有几个不成文的基本原则:

  对共享资源操作前一定要获得锁。

  完成操作以后一定要释放锁。

  尽量短时间地占用锁。

  如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。

  线程错误返回时应该释放它所获得的锁。

下面是一段测试代码,创建两个线程,分别访问全局变量gnum,并且修改它,打印出来

/*mutex.c*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
/*全局变量*/
int gnum = 0;
/*互斥量 */
pthread_mutex_t mutex;
/*声明线程运行服务程序*/
static void pthread_func_1 (void);
static void pthread_func_2 (void);

int main (void)
{
 /*线程的标识符*/
  pthread_t pt_1 = 0;
  pthread_t pt_2 = 0;
  int ret = 0;
  /*互斥初始化*/
  pthread_mutex_init (&mutex, NULL);
  /*分别创建线程1、2*/
  ret = pthread_create( &pt_1,                  //线程标识符指针
                                     NULL,                  //默认属性
                                     (void *)pthread_func_1,//运行函数
                                     NULL);                  //无参数
  if (ret != 0)
  {
     perror ("pthread_1_create");
  }

ret = pthread_create( &pt_2,                  //线程标识符指针
                                     NULL,                   //默认属性
                                     (void *)pthread_func_2, //运行函数
                                     NULL);                  //无参数
  if (ret != 0)
  {
     perror ("pthread_2_create");
  }
  /*等待线程1、2的结束*/
  pthread_join (pt_1, NULL);
  pthread_join (pt_2, NULL);

printf ("main programme exit!/n");
  return 0;
}
/*线程1的服务程序*/
static void pthread_func_1 (void)
{
  int i = 0;

for( i=0; i<3; i++ ){
    printf ("This is pthread_1!/n");
    pthread_mutex_lock(&mutex); /*获取互斥锁*/
        /*注意,这里以防线程的抢占,以造成一个线程在另一个线程sleep时多次访问互斥资源,所以sleep要在得到互斥锁后调用*/
    sleep (1);
    /*临界资源*/
    gnum++;
    printf ("Thread_1 add one to num:%d/n",gnum);
    pthread_mutex_unlock(&mutex); /*释放互斥锁*/
  }

pthread_exit ( NULL );
}
/*线程2的服务程序*/
static void pthread_func_2 (void)
{
  int i = 0;

for( i=0; i<5; i++ )  {
    printf ("This is pthread_2!/n");
    pthread_mutex_lock(&mutex); /*获取互斥锁*/
        /*注意,这里以防线程的抢占,以造成一个线程在另一个线程sleep时多次访问互斥资源,所以sleep要在得到互斥锁后调用*/
    sleep (1);
    /*临界资源*/
    gnum++;
    printf ("Thread_2 add one to num:%d/n",gnum);
    pthread_mutex_unlock(&mutex); /*释放互斥锁*/

}

pthread_exit ( NULL );
}

参考来源于网络:

http://baike.baidu.com/view/4518300.html

http://baike.baidu.com/view/1461738.htm

http://blog.csdn.net/benny_cen/article/details/3969219

http://blog.csdn.net/xing_hao/article/details/6626223

http://hi.baidu.com/cunlin/blog/item/1f9e3f384c6bbeffb211c79c.html

http://blog.chinaunix.net/space.php?uid=20698441&do=blog&id=1891215

互斥锁 pthread_mutex_init()函数的更多相关文章

  1. 互斥锁pthread_mutex_init()函数

    linux下为了多线程同步,通常用到锁的概念.posix下抽象了一个锁类型的结构:ptread_mutex_t.通过对该结构的操作,来判断资源是否可以访问.顾名思义,加锁(lock)后,别人就无法打开 ...

  2. Linux互斥锁、条件变量和信号量

    Linux互斥锁.条件变量和信号量  来自http://kongweile.iteye.com/blog/1155490 http://www.cnblogs.com/qingxia/archive/ ...

  3. linux 2.6 互斥锁的实现-源码分析

    http://blog.csdn.net/tq02h2a/article/details/4317211 看了看linux 2.6 kernel的源码,下面结合代码来分析一下在X86体系结构下,互斥锁 ...

  4. 【TencentOS tiny】深度源码分析(6)——互斥锁

    互斥锁 互斥锁又称互斥互斥锁,是一种特殊的信号量,它和信号量不同的是,它具有互斥锁所有权.递归访问以及优先级继承等特性,在操作系统中常用于对临界资源的独占式处理.在任意时刻互斥锁的状态只有两种,开锁或 ...

  5. 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 百篇博客分析OpenHarmony源码 | v27.02

    百篇博客系列篇.本篇为: v27.xx 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立贞 ...

  6. pthread_mutex_init & 互斥锁pthread_mutex_t的使用

    pthread_mutex_init l         头文件: #include <pthread.h> l         函数原型: int pthread_mutex_init( ...

  7. 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发

    子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...

  8. Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量

    Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程:    1.线程是一堆指令,是操作系统调度 ...

  9. linux c学习笔记----互斥锁属性

    转自:http://lobert.iteye.com/blog/1762844 互斥锁属性 使用互斥锁(互斥)可以使线程按顺序执行.通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程. ...

随机推荐

  1. 初涉JSP+JDBC 基于SQL2008的登陆验证程序

    简单的以代码的形式纪念一下,因为现在还没有解决SQL2008驱动的问题,并且有好多东西要学,所以日后会有更新~ 所安装的软件有:SQL2008,eclipse,tomcat,JDK,涉及环境配置.等等 ...

  2. jquery前端第一讲

    1.bootstrap里面的文件是什么意思: bootstrap.cssbootstrap.min.cssbootstrap-responsive.cssbootstrap-responsive.mi ...

  3. APP分析----饿了么

    产品      饿了么 选择原因:有了外卖就可以轻松拥有一个不用出门也饿不着的爽歪歪周末. 第一部分 调研, 评测 下载软件并使用起来,描述最简单直观的个人第一次上手体验. 主界面: 第一次上手是大一 ...

  4. 在虚拟机中安装Ubuntu详细过程

    参考:http://blog.csdn.net/u013142781/article/details/50529030

  5. 封装GetQueryString()方法来获取URL的value值(转载)

    首先测试URL:http://192.168.1.82:8020/juzhong/daojishi.html?name=xiangruding&sex=nuuu&age=90 代码如下 ...

  6. apache +PHP多版本 切换的问题

    在开发中切换php版本的时候出错 经过2小时的日子排查终于找到是因为切换版本后加载的php7ts.dll模块还是原来版本的,因此保pid file 错误 解决方法 PHPIniDir "H: ...

  7. Windows 配置Reids集群 Redis Cluster

    一 .所需软件:Redis.Ruby语言运行环境.Redis的Ruby驱动redis-xxxx.gem.创建Redis集群的工具redis-trib.rb 二 .安装配置redis  redis下载地 ...

  8. MySQL复合主键下ON DUPLICATE KEY UPDATE语句失效问题

    问题的起因,假设有一张表,里面保存了交易订单,每张订单有唯一的ID,有最后更新时间,还有数据,详情如下: 1 2 3 4 5 6 7 +-------+----------+------+-----+ ...

  9. SecureCRT8.1下载+注册机+破解教程

    [下载]下载SecureCRT + SecureFX 8.1 Bundle版本软件,官网下载较麻烦,因此在此提供百度云连接. 链接:http://pan.baidu.com/s/1hsIjtSK 密码 ...

  10. Digits of Factorial LightOJ - 1045(数学题?)

    原文地址: https://blog.csdn.net/fenghoumilin/article/details/52293910 题意:求 n 的阶乘在 base 进制下的位数,这里有一个简单的方法 ...