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线程同步:互斥量,死锁的相关文章

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

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

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

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

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);//撤销互斥量 不能拷贝互斥量变量,但可以拷贝指向互斥量的指针,这样就可以使多个函数

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你的线程和外面的线程同步?程序模块的设计商是不是有问

线程同步经典问题,和尚挑水问题

问题描述 线程同步经典问题,和尚挑水问题 某寺庙有小和尚.老和尚若干.庙内有一水缸.由小和尚提水入缸,供老和尚饮用.水缸可容纳10桶水,每次入水.取水都为1桶,且不可同时进行.水取自同一井中,水井口很小,每次只能容纳一只水桶取水.设水桶个数为3个.试写出小和尚和老和尚的函数,假设有5个小和尚提水入缸,5个老和尚取水喝(每隔一定时间取水一次),分别用不同的线程模拟小和尚和老和尚,使他们能同步进行.(每个和尚一个线程) 解决方案 using System; using System.Collecti

Android多线程研究(3)线程同步和互斥及死锁

为什么会有线程同步的概念呢?为什么要同步?什么是线程同步?先看一段代码: package com.maso.test; public class ThreadTest2 implements Runnable{ private TestObj testObj = new TestObj(); public static void main(String[] args) { ThreadTest2 tt = new ThreadTest2(); Thread t1 = new Thread(tt,

类-MFC多线程同步问题,互斥量

问题描述 MFC多线程同步问题,互斥量 共享资源是一些类对象的MAP,每个对象(某设备实例)中有不同的互斥量同步不同的类变量(本意是防止多线程访问同一个对象),现在迷糊了,互斥量放在类里面是不是不当?是不是在访问对象的时候就加互斥量来的方便(对整个对象进行加锁 - 因为对整个类操作较多,这么做貌似锁太深了)?求大神帮助 解决方案 这个要具体看对象的生存空间,和互斥量的作用!无法一概而论. 解决方案二: 搞这么麻烦干什么,线程同步直接用CreateMutex和WaitForSingleObject