Pthread线程 —— 多线程同步 互斥锁(mutex)

来源:互联网 发布:域名网 编辑:程序博客网 时间:2024/06/09 16:56

多线程的同步机制

  对于多线程程序来说,同步(synchronization)是指在一定的时间内只允许某一个线程访问某个资源 。而在此时间内,不允许其它的线程访问该资源。Linux下提供了多种方式来处理线程同步,最常用的是互斥锁(mutex)条件变量(condition variable)信号量(sem)

互斥锁(mutex)

  互斥锁是一个特殊的变量,它有锁上(lock)打开(unlock)两个状态。互斥锁一般被设置成全局变量。打开的互斥锁可以由某个线程获得。一旦获得,这个互斥锁会锁上,此后只有该线程有权打开。其它想要获得互斥锁的线程,会等待直到互斥锁再次打开的时候。我们可以将互斥锁想像成为一个只能容纳一个人的洗手间,当某个人进入洗手间的时候,可以从里面将洗手间锁上。其它人只能在互斥锁外面等待那个人出来,才能进去。在外面等候的人并没有排队,谁先看到洗手间空了,就可以首先冲进去。
  互斥锁的使用过程中,主要有pthread_mutex_init,pthread_mutex_destory,pthread_mutex_lock,pthread_mutex_unlock这几个函数以完成锁的初始化,锁的销毁,上锁和释放锁操作。
  pthread_mutex_t 的定义:

typedef union{    struct __pthread_mutex_s    {        int __lock;        unsigned int __count;        int __owner;#if __WORDSIZE == 64        unsigned int __nusers;#endif        /* KIND must stay at this position in the structure to maintain             binary compatibility.  */        int __kind;#if __WORDSIZE == 64        int __spins;        __pthread_list_t __list;#define __PTHREAD_MUTEX_HAVE_PREV      1#else        unsigned int __nusers;        __extension__ union        {            int __spins;            __pthread_slist_t __list;        };#endif    } __data;    char __size[__SIZEOF_PTHREAD_MUTEX_T];    long int __align;} pthread_mutex_t;

锁的创建

  锁可以被动态或静态创建,可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,采用这种方式比较容易理解,互斥锁是pthread_mutex_t的结构体,而这个宏是一个结构常量,如下可以完成静态的初始化锁:

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
另外锁可以用pthread_mutex_init函数动态的创建,函数原型如下:
    int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)

锁的属性

  互斥锁属性可以由 pthread_mutexattr_init(pthread_mutexattr_t *mattr); 来初始化,然后可以调用其他的属性设置方法来设置其属性;
  互斥锁的类型:有以下几个取值空间:

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

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

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

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

可以用

pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)

获取或设置锁的类型。

锁的释放

  调用pthread_mutex_destory之后,可以释放锁占用的资源,但这有一个前提上锁当前是没有被锁的状态。

锁的操作

  对锁的操作主要包括加锁 pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个。

    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而不是挂起等待

锁的使用

#include <pthread.h>  #include <stdio.h>  pthread_mutex_t mutex ;void *print_msg(void *arg){      int i=0;      pthread_mutex_lock(&mutex);      for(i=0;i<15;i++)    {          printf("output : %d\n",i);          usleep(100);      }      pthread_mutex_unlock(&mutex);  }  int main(int argc,char** argv){      pthread_t id1;      pthread_t id2;      pthread_mutex_init(&mutex,NULL);      pthread_create(&id1,NULL,print_msg,NULL);      pthread_create(&id2,NULL,print_msg,NULL);      pthread_join(id1,NULL);      pthread_join(id2,NULL);      pthread_mutex_destroy(&mutex);      return 1;  }  

总结

  关于互斥锁,可能有些地方,不太容易懂。比如,互斥锁锁什么?简单的来说,互斥锁用的限制在同一时刻,其他的线程执行pthread_mutex_lock和pthread_mutex_unlock之间的指令。
  

0 0
原创粉丝点击