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

多线程的同步机制

  对于多线程程序来说,同步(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   
#include   

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之间的指令。
  

你可能感兴趣的:(Linux,学习,多线程,互斥锁)