1线程同步:互斥量,死锁



1线程为什么要同步

A:共享资源,多个线程都可对共享资源操作。

B:线程操作共享资源的先后顺序不确定。

C:处理器对存储器的操作一般不是原子操作。

2互斥量

mutex操作原语

pthread_mutex_t

pthread_mutex_init

pthread_mutex_destroy

pthread_mutex_lock

pthread_mutex_trylock

pthread_mutex_unlock

3临界区(Critical Section)

保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。

4临界区的选定

   临界区的选定应尽可能小,如果选定太大会影响程序的并行处理性能。

5互斥量实例

依赖的头文件

#include<pthread.h>

函数声明

int pthread_mutex_destroy(pthread_mutex_t*mutex);

名称:

pthread_mutex_destroy

功能:

释放对互斥变量分配的资源

头文件:

#include <pthread.h>

函数原形:

int  pthread_mutex_destroy(pthread_mutex_t *mutex);

参数:

 

返回值:

若成功则返回0,否则返回错误编号。

 

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

名称:

pthread_mutexattr_init

功能:

初始化互斥锁。

头文件:

#include <pthread.h>

函数原形:

int pthread_mutex_init(pthread_mutex_t * mutex,

const pthread_mutex_t *attr);

参数:

mutex 互斥量

attr    互斥锁属性

返回值:

若成功则返回0,否则返回错误编号。

int pthread_mutex_lock(pthread_mutex_t*mutex);

int pthread_mutex_trylock(pthread_mutex_t*mutex);

int pthread_mutex_unlock(pthread_mutex_t*mutex);

名称:

pthread_mutex_lock/ pthread_mutex_trylock/ pthread_mutex_unlock

功能:

对互斥量加/减锁

头文件:

#include <pthread.h>

函数原形:

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

参数:

 

返回值:

若成功则返回0,否则返回错误编号。

函数说明:

对互斥量进行加锁,需要调用pthread_mutex_lock,如果互斥量已经上锁,调用线程阻塞直至互斥量解锁。对互斥量解锁,需要调用pthread_mutex_unlock.

      如果线程不希望被阻塞,他可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,否则就会失败,不能锁住互斥量,而返回EBUSY。

 

6互斥锁创建

有两种方法创建互斥锁,静态方式和动态方式。

A:POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下:

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

B:动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下:

int pthread_mutex_init(pthread_mutex_t *mutex, constpthread_mutexattr_t *mutexattr);

其中mutexattr用于指定互斥锁属性,如果为NULL则使用缺省属性。

C:pthread_mutex_destroy
()用于注销一个互斥锁,API定义如下:

   intpthread_mutex_destroy(pthread_mutex_t *mutex);

D:pthread_mutex_lock()加锁

E:pthread_mutex_unlock()解锁

F:pthread_mutex_trylock()测试加锁

G:释放内存前需要调用pthread_mutex_destory.

案例说明互斥量加锁的必要性:

#include<stdio.h>

#include<pthread.h>

#include<stdlib.h>

#include<unistd.h>

 

void *thread_function(void *arg);

/*用run_now代表共享资源*/

int run_now = 1;

 

int main(void)

{

   int print_count1 = 0;/*用于循环控制*/

   pthread_t a_thread;

 

   /*创建一个进程*/

   if(pthread_create(&a_thread,NULL,thread_function,NULL)){

       perror("Thread creation failed!");

       exit(1);

   }

 

   while(print_count1++ < 5){

       /*主线程:如果run_now为1就把它修改为2*/

       if(run_now == 1) {

           printf("main thread is run\n");

           run_now = 2;

       } else {

           printf("main thread is sleep\n");

           sleep(1);

       }

   }

        //等待子线程结束

   pthread_join(a_thread,NULL);

   exit(0);

}

 

void *thread_function(void *arg) {

  int print_count2 = 0;

  while(print_count2++ < 5){

      if(run_now == 2) /*子线程:如果run_now为1就把它修改为1*/

      {

          printf("function thread is run\n");

          run_now = 1;

      }

      else

      {

          printf("function thread is sleep\n");

          sleep(1);

      }

  }

  pthread_exit(NULL);

}

运行结果:

现象:main线程和function线程是交替运行的。它们都可以对run_now进行操作。

加锁后的代码

#include <stdio.h>

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

 

void *thread_function(void *arg);

int run_now=1; /*用run_now代表共享资源*/

pthread_mutex_t work_mutex; /*定义互斥量*/

 

int main(void) {

   int res;

   int print_count1=0;

   pthread_t a_thread;

 

   if(pthread_mutex_init(&work_mutex,NULL)!=0) /*初始化互斥量*/

   {

       perror("Mutex init faied");

       exit(1);

   }

 

   if(pthread_create(&a_thread,NULL,thread_function,NULL)!=0) /*创建新线程*/

   {

       perror("Thread createion failed");

       exit(1);

   }

 

   if(pthread_mutex_lock(&work_mutex)!=0) /*对互斥量加锁*/

   {

       perror("Lock failed");

       exit(1);

   } else {

       printf("main lock\n");

   }

 

   while(print_count1++<5) {

       if(run_now == 1) /*主线程:如果run_now为1就把它修改为2*/

       {

           printf("main thread is run\n");

           run_now=2;

       } else {

           printf("main thread is sleep\n");

           sleep(1);

       }

   }

 

   if(pthread_mutex_unlock(&work_mutex)!=0) /*对互斥量解锁*/

   {

       perror("unlock failed");

       exit(1);

   } else {

       printf("main unlock\n");

   }

 

   pthread_mutex_destroy(&work_mutex); /*收回互斥量资源*/

   pthread_join(a_thread,NULL); /*等待子线程结束*/

   exit(0);

}

 

void *thread_function(void *arg) {

   int print_count2=0;

   sleep(1);

 

   if(pthread_mutex_lock(&work_mutex)!=0) {

       perror("Lock failed");

       exit(1);

   } else {

       printf("function lock\n");

   }

   

   while(print_count2++<5) {

       if(run_now==2) /*分进程:如果run_now为1就把它修改为1*/

       {

           printf("function thread is run\n");

           run_now=1;

       } else {

           printf("function thread is sleep\n");

           sleep(1);

       }

   }

 

   if(pthread_mutex_unlock(&work_mutex)!=0) /*对互斥量解锁*/

   {

       perror("unlock failed");

       exit(1);

   } else {

       printf("function unlock\n");

   }

   pthread_exit(NULL);

}

运行结果如下:

总结:从运行结果可以看到,当主进程把互斥量锁住后,子进程就不能对共享资源进行操作了,只能是同步的操作了。

#include<stdio.h>

#include<stdlib.h>

#include<pthread.h>

#define NLOOP 5000

 

int counter;

pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

 

void *doit(void *);

 

int main(int argc,char **argv){

   pthread_t tidA,tidB;

 

   pthread_create(&tidA,NULL,doit,NULL);

   pthread_create(&tidB,NULL,doit,NULL);

 

   /*wait for both thread to terminate*/

   pthread_join(tidA,NULL);

   pthread_join(tidB,NULL);

 

   return 0;

}

 

void *doit(void *vptr){

   int i,val;

   for(i = 0;i < NLOOP;i++) {

       pthread_mutex_lock(&counter_mutex);

       val = counter;

       printf("%x:%d\n",(unsigned int) pthread_self(),val + 1);

       counter = val + 1;

 

       pthread_mutex_unlock(&counter_mutex);

   }

 

   return NULL;

}

运行结果:

  1. 死锁

    A同一个线程在拥有A锁的情况下再次请求获得A锁

    B线程一拥有A锁,请求获得B锁;线程二拥有B锁,请求获得A锁,出现死锁,最终导致的结果是互相等待。

时间: 2014-09-25

1线程同步:互斥量,死锁的相关文章

二、(LINUX 线程同步) 互斥量、条件变量以及生产者消费者问题

原创转载请注明出处: 接上一篇: 一.(LINUX 线程同步) 引入  http://blog.itpub.net/7728585/viewspace-2137980/ 在线程同步中我们经常会使用到mutex互斥量,其作用用于保护一块临界区,避免多线程并发操作对这片临界区带来的数据混乱, POSIX的互斥量是一种建议锁,因为如果不使用互斥量也可以访问共享数据,但是可能是不安全的. 其原语包含: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

四种进程或线程同步互斥的控制方法

进程|控制 很想整理一下自己对进程线程同步互斥的理解.正巧周六一个刚刚回到学校的同学请客吃饭.在吃饭的过程中,有两个同学,为了一个问题争论的面红耳赤.一个认为.Net下的进程线程控制模型更加合理.一个认为Java下的线程池策略比.Net的好.大家的话题一下转到了进程线程同步互斥的控制问题上.回到家,想了想就写了这个东东.  现在流行的进程线程同步互斥的控制机制,其实是由最原始最基本的4种方法实现的.由这4种方法组合优化就有了.Net和Java下灵活多变的,编程简便的线程进程控制手段.  这4种方

同步-互斥量 临界区 信号量 条件变量 效率对比

问题描述 互斥量 临界区 信号量 条件变量 效率对比 windows 下,如下四种同步方式中,互斥量 临界区 信号量 条件变量, 效率对比,求指导,谢谢 解决方案 据我自己在windows下的测试,信号量比条件变量高效,大概是其6倍 解决方案二: 条件变量效率应该最高,但是可能不是那么线程安全 临界区效率第二好 解决方案三: 临界区(Critical Section)(同一个进程内,实现互斥) 保证在某一时刻只有一个线程能访问数据的简便办法.在任意时刻只允许一个线程对共享资源进行访问.如果有多个

Linux多线程使用互斥量同步线程_Linux

本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两个信号量才能解决的只有子线程结束了对输入的处理和统计后,主线程才能继续执行的问题. 一.什么是互斥量 互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它.为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁. 二.互斥量的函数的使用 它们的定义与使用信号量的函数非常相似,它们的定义如下: #include <pthread.h> int pthre

UNIX环境高级编程:线程同步之互斥量

互斥量(也称为互斥锁)出自POSIX线程标准,可以用来同步同一进程中的各个线程.当然如果一个互斥量存放在多个进程共享的某个内存区中,那么还可以通过互斥量来进行进程间的同步. 互斥量,从字面上就可以知道是相互排斥的意思,它是最基本的同步工具,用于保护临界区(共享资源),以保证在任何时刻只有一个线程能够访问共享的资源. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 1互斥量初始化和销毁 #include <pthread

UNIX环境高级编程:线程同步之互斥锁、读写锁和条件变量

一.使用互斥锁 1.初始化互斥量 pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥量 int pthread_mutex_init(pthread_mutex_t*mutex,pthread_mutexattr_t*attr);//动态初始化互斥量 int pthread_mutex_destory(pthread_mutex_t*mutex);//撤销互斥量 不能拷贝互斥量变量,但可以拷贝指向互斥量的指针,这样就可以使多个函数

linux之线程之互斥

线程概述: 其实在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone().该系统copy了一个和原先进程完全一样的进程,并在这 个进程中执行线程函数.不过这个copy过程和fork不一样.copy后的进程和原先的进程共享了所有的变量,运行环境.这样,原先进程中的变量变动在 copy后的进程中便能体现出来. 大部分多线程程序需要在线程间共享数据.如果两个线程同时访问共享数据就可能有问题,因为一个线程可能在另一个线程修改共享数据的过程中使用该数据:并认为共享数据保持不变

UNIX环境高级编程:互斥量属性

互斥量具有一些属性,通过修改这些属性可以控制锁的一些行为.缺省的互斥锁属性及其值如下: pshared:         PTHREAD_PROCESS_PRIVATE type:                 PTHREAD_MUTEX_DEFAULT protocol:          PTHREAD_PRIO_NONE prioceiling:       – robustness:    PTHREAD_MUTEX_STALLED_NP 1.获得/修改共享互斥量属性 pthread_

UNIX环境高级编程:线程同步之条件变量及属性

条件变量变量也是出自POSIX线程标准,另一种线程同步机制.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来进行进程间的同步. 每个条件变量总是和一个互斥量相关联,条件本身是由互斥量保护的,线程在改变条件状态之间必须要锁住互斥量.条件变量相对于互斥量最大的优点在于允许线程以无竞争的方式等待条件的发生.当一个线程获得互斥锁后,发现自己需要等待某个条件变为真,如果是这样,该线程就可以等待在某个条件上,这样就不

关于dll与调用者线程同步的问题

问题描述 关于dll与调用者线程同步的问题 Dll导出函数创建了一个线程,该线程与该函数的调用者所在的线程如何同步? 解决方案 线程之间 的同步机制就那么几个,无论线程是否是从 DLL 导出的,使用的方法还是一样的,如:windows多线程--原子操作windows多线程同步--事件windows多线程同步--互斥量windows多线程同步--临界区windows多线程同步--信号量 Linux 下有类似的机制. 解决方案二: 为什么需要dll你的线程和外面的线程同步?程序模块的设计商是不是有问