zoukankan      html  css  js  c++  java
  • pThreads线程(二) 线程同步--互斥量/锁

      互斥量(Mutex)是“mutual exclusion”的缩写。互斥量是实现线程同步,和保护同时写共享数据的主要方法。
      互斥量对共享数据的保护就像一把锁。在Pthreads中,任何时候仅有一个线程可以锁定互斥量,因此,当多个线程尝试去锁定该互斥量时仅有一个会成功。直到锁定互斥量的线程解锁互斥量后,其他线程才可以去锁定互斥量。线程必须轮着访问受保护数据。
      
    一个拥有互斥量的线程经常用于更新全局变量。确保了多个线程更新同样的变量以安全的方式运行,最终的结果和一个线程处理的结果是相同的。这个更新的变量属于一个“临界区(critical section)”。


      使用互斥量的典型顺序如下:

    • 创建和初始一个互斥量
    • 多个线程尝试去锁定该互斥量
    • 仅有一个线程可以成功锁定改互斥量
    • 锁定成功的线程做一些处理
    • 线程解锁该互斥量
    • 另外一个线程获得互斥量,重复上述过程
    • 最后销毁互斥量

      当多个线程竞争同一个互斥量时,失败的线程会阻塞在lock调用处。可以用“trylock”替换“lock”,则失败时不会阻塞。当保护共享数据时,程序员有责任去确认是否需要使用互斥量。如,若四个线程会更新同样的数据,但仅有一个线程用了互斥量,则数据可能会损坏。

    创建和销毁互斥量:

    pthread_mutex_init (mutex,attr)  
    pthread_mutex_destroy (mutex)  
    pthread_mutexattr_init (attr)  
    pthread_mutexattr_destroy (attr) 

    用法

    互斥量必须用类型pthread_mutex_t类型声明,在使用前必须初始化,这里有两种方法可以初始化互斥量:
    声明时静态地,如: pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
    动态地用pthread_mutex_init()函数,这种方法允许设定互斥量的属性对象attr。
    互斥量初始化后是解锁的。
    attr对象用于设置互斥量对象的属性,使用时必须声明为pthread_mutext_attr_t类型,默认值可以是NULL。Pthreads标准定义了三种可选的互斥量属性:

    • 协议(Protocol): 指定了协议用于阻止互斥量的优先级改变
    • 优先级上限(Prioceiling):指定互斥量的优先级上限
    • 进程共享(Process-shared):指定进程共享互斥量

    注意所有实现都提供了这三个可先的互斥量属性。
    pthread_mutexattr_init()和pthread_mutexattr_destroy()函数分别用于创建和销毁互斥量属性对象。
    pthread_mutex_destroy()应该用于释放不需要再使用的互斥量对象。

    锁定和解锁互斥量:

    函数

    pthread_mutex_lock (mutex)  
    pthread_mutex_trylock (mutex)  
    pthread_mutex_unlock (mutex)  

    用法

    线程用pthread_mutex_lock()函数去锁定指定的mutex变量,若该mutex已经被另外一个线程锁定了,该调用将会阻塞线程直到mutex被解锁。
    pthread_mutex_trylock() will attempt to lock a mutex. However, if the mutex is already locked, the routine will return immediately with a "busy" error code. This routine may be useful in pthread_mutex_trylock().

      尝试着去锁定一个互斥量,然而,若互斥量已被锁定,程序会立刻返回并返回一个忙错误值。该函数在优先级改变情况下阻止死锁是非常有用的。线程可以用pthread_mutex_unlock()解锁自己占用的互斥量。在一个线程完成对保护数据的使用,而其它线程要获得互斥量在保护数据上工作时,可以调用该函数。若有一下情形则会发生错误:

    • 互斥量已经被解锁
    • 互斥量被另一个线程占用

    互斥量并没有多么“神奇”的,实际上,它们就是参与的线程的“君子约定”。写代码时要确信正确地锁定,解锁互斥量。
    Q:有多个线程等待同一个锁定的互斥量,当互斥量被解锁后,那个线程会第一个锁定互斥量?
    A:除非线程使用了优先级调度机制,否则,线程会被系统调度器去分配,那个线程会第一个锁定互斥量是随机的。

    用例: 

     1 #include<stdlib.h>  
     2 #include<stdio.h>  
     3 #include<unistd.h>  
     4 #include<pthread.h>  
     5 
     6 typedef struct ct_sum  
     7 { 
     8     int sum;  
     9     pthread_mutex_t lock;  
    10 }ct_sum;  
    11 
    12 void * add1(void *cnt)  
    13 {       
    14     pthread_mutex_lock(&(((ct_sum*)cnt)->lock));  
    15     for(int i=0; i < 50; i++)  
    16     {
    17         (*(ct_sum*)cnt).sum += i;      
    18     }  
    19     pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));  
    20     pthread_exit(NULL);  
    21     return 0;  
    22 }  
    23 void * add2(void *cnt)  
    24 {        
    25     pthread_mutex_lock(&(((ct_sum*)cnt)->lock));  
    26     for(int i=50; i<101; i++)  
    27     {   
    28          (*(ct_sum*)cnt).sum += i;    
    29     }  
    30     pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));  
    31     pthread_exit(NULL);  
    32     return 0;  
    33 }  
    34   
    35 int main(void)  
    36 {
    37     pthread_t ptid1, ptid2;  
    38     ct_sum cnt;  
    39     pthread_mutex_init(&(cnt.lock), NULL);  
    40     cnt.sum=0;  
    41   
    42     pthread_create(&ptid1, NULL, add1, &cnt);  
    43     pthread_create(&ptid2, NULL, add2, &cnt);  
    44    
    45     pthread_join(ptid1,NULL);  
    46     pthread_join(ptid2,NULL);
    47 
    48     printf("sum %d
    ", cnt.sum);
    49     pthread_mutex_destroy(&(cnt.lock));  
    50 
    51     return 0;  
    52 }  
  • 相关阅读:
    adodb.stream文件操作类详解
    Html中Label标记的作用和使用介绍
    正则表达式的威力轻松消除HTML代码
    只需一行代码就能让IE 6崩溃
    码农干货系列【17】Wind.js与Promise.js
    码农干货系列【3】割绳子(cut the rope)制作点滴:旋转(rotation)
    HTML5 Canvas开发者和读者的福音
    码农干货系列【8】世界上最简单的3D渲染(no webgl)
    码农干货系列【18】getting started with Promise.js(总)
    ProgressForm
  • 原文地址:https://www.cnblogs.com/dongsheng/p/4186358.html
Copyright © 2011-2022 走看看