Pthreads多线程编程(3)

来源:互联网 发布:macbook windows 截屏 编辑:程序博客网 时间:2024/06/06 04:20
互斥量

1.  概述
Mutex是"mutual exclusion"的缩写,互斥量是完成线程同步和在并发操作中保护共享数据的一种主要方法。
  • 互斥量在保护共享数据资源时的行为类似于"锁"。在多线程中,任何时候只有一个线程可以持有互斥量。因此,即使有多个线程尝试去持有某个互斥量,只有一个线程可以成功。多个线程必须轮流访问被保护的共享数据。
  • 互斥量可以用来避免竞争条件。下图是一个涉及到银行业务的竞争条件。
  • Thread 1Thread 2BalanceRead balance: $1000 $1000 Read balance: $1000$1000 Deposit $200$1000Deposit $200 $1000Update balance $1000+$200 $1200 Update balance $1000+$200$1200
  • 在上面的例子中,当一个线程在读写共享数据时,应该用一个互斥量来锁住"Balance".
  • 互斥量常见的一个应用是在更新全局变量时,被更新的全局变量属于临界区。
  • 在使用互斥量时,一般有以下几步: 
              (1) 创建和初始化互斥量。
              (2) 多个线程尝试持有该互斥量。
              (3) 第(2)步中,只有一个线程成功持有该互斥量。
              (4) 持有互斥锁的线程执行指令。
              (5) 释放互斥锁。
              (6) 另外一个线程获取互斥锁,并执行一些操作。
              (7) 销毁互斥锁。
  • 当多个线程竞争一个互斥锁时,失败的线程会被阻塞。(使用trylock函数可以避免阻塞)      
  • 保护共享数据时,程序员应该保证每个应该使用互斥锁的线程使用互斥锁。例如:如果有四个线程都要更新某个全局变量,只有一个线程使用互斥锁,数据也会被毁坏。
2.  创建和销毁互斥锁
  • 函数
  • pthread_mutex_init (mutex,attr)

    pthread_mutex_destroy (mutex)

    pthread_mutexattr_init (attr)

    pthread_mutexattr_destroy (attr)

  • 用法
               (1) 互斥量被声明成pthread_mutex_t类型,在使用之前必须被初始化。有两种方法来初始化互斥量:
                     a. 静态初始化。在声明时初始化。     pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
                     b. 动态初始化。 使用pthread_mutex_init()来初始化。
               (2) attr属性用来建立互斥锁的性质,必须是pthread_mutexattr_t类型, Pthread标准定义了三种可选的mutex属性:
                    a. 协议:指定用来避免优先级反转的协议。
                    b. 优先级上限:指定互斥锁的优先级上限。
                    c. 进程共享:指定互斥锁的进程共享。
               (3) 函数pthread_mutexattr_init()和pthread_mutexattr_destory() 用来创建和销毁互斥锁属性。
               (4) pthread_mutex_destory()函数用来释放互斥锁。
3. 互斥锁操作:加锁及解锁
  • 函数
  • pthread_mutex_lock (mutex)

    pthread_mutex_trylock (mutex)

    pthread_mutex_unlock (mutex)

  • 用法
          (1) pthread_mutex_lock()函数用来获取某个互斥量的锁,如果已经被其他线程加锁,调用pthread_mutex_lock()的线程会被阻塞。
          (2) pthread_mutex_trylock()函数也用来给互斥量加锁,如果该互斥量已经被其他线程加锁,该函数会返回"busy"信息,这个函数一般用在避免死锁时,例如优先级翻转问题。
          (3) pthread_mutex_unlock()函数用来解锁互斥量。 以下情况回返回错误:
              a. 如果互斥量已经被解锁。
              b. 互斥锁被其他线程所有。
          (4) 互斥锁类似于多个线程之间都遵守的约定,依赖于程序开发者正确的加锁及解锁。
          Question: 当多个线程在等待获取锁时, 哪个线程会最先获取?
          Answer:在没有线程优先级调度策略时,互斥锁的分配依赖于native system scheduler,比较随机。

条件变量
                                                                                                                                                                                                                                       
1. 概述
  • 条件变量提供多线程间同步的另一种方式。互斥锁通过控制线程读写数据来实现同步,而条件变量  通过数据的实际值来实现同步。
  • 在没有竞争变量的条件下,开发者需要使得线程不停的轮询,来检查条件是否满足。这种机制非常耗费资源,可以使用条件变量来代替这种机制。
  • 条件变量一般和互斥锁一起使用。
  • 使用条件变量的典型步骤如下:
                                    
 2. 创建和销毁条件变量
  • 函数
pthread_cond_init (condition,attr)

pthread_cond_destroy (condition)

pthread_condattr_init (attr)


pthread_condattr_destroy (attr)
  • 用法
      (1) 条件变量必须声明为pthread_cond_t类型,在使用之前必须初始化。 有两种方式来初始化条件变量:
           a. 静态初始化。
               pthread_cond_t myconvar = PTHREAD_COND_INITIALIZER;
           b. 动态初始化。使用函数pthread_cond_init()来初始化,条件变量的ID通过条件参数返回给调用线程,改函数可以设置条件变量属性。
      (2) 可选参数attr用来设置条件变量的属性。只有一种属性:process_shared, 允许条件变量在其他进程可见。
      (3)  pthread_condattr_init(),pthread_condattr_destroy()函数用来创建和销毁条件变量属性。
      (4) pthread_cond_destroy()函数用来释放条件变量。
3. 等待和唤醒条件变量 
  • 函数
     
pthread_cond_wait (condition,mutex)

pthread_cond_signal (condition)

pthread_cond_broadcast (condition)


  • 用法
     (1)  pthread_cond_wait()会阻塞调用该函数的线程直到收到条件变量满足的信号。该函数应该在mutex locked之后被调用,在等待阶段,它会自动释放互斥锁,在收到信号,线程被唤醒后,mutex会自动加       锁。最后由开发人员负责释放互斥锁。
        建议:用WHILE循环替换IF语句来检测条件变量,可以避免一些潜在的问题:
                  a. 如果有多个线程在等待同一个唤醒信号,会轮流获取互斥锁,其中每个线程都可以改变条件变量。
                  b. 当程序失败时,线程收到错误信号。
                  c. 线程库允许发出假的唤醒信号。
     (2) pthread_cond_signal()函数用来发出信号唤醒另外一个正在等待条件变量的线程。应该在mutex lock之后调用。
     (3) 如果有多个线程阻塞在等待状态,用函数pthread_cond_broadcast()来代替pthread_cond_signal()来唤醒线程。
     (4) 在调用pthread_cond_wait()之前调用pthread_cond_signal()是逻辑错误。
      正确的给互斥量加锁及解锁在多线程中是很关键的:
      a. 在调用pthread_cond_wait()之前未能正确加锁该线程不会被阻塞。
      b. 在调用pthread_cond_signal()之后,如果没有正确的解锁,会使得满则竞争条件的线程继续阻塞。
       
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 太阳能板只有电压没有电流怎么办 农村按空调房屋不保温怎么办 自己一个人想去足疗店不敢去怎么办 吊灯led灯坏了怎么办 办健身卡老板携款跑路了怎么办 武安丰尚健身怎么办卡 热敷后眼睛肿了怎么办 两眼视力差距大怎么办 怀孕体重长得快怎么办 怀孕初期发胖6斤怎么办 孕早期长得太快怎么办 怀孕了肚子眼脏怎么办 孕38周孩子偏小怎么办 孕初期胖的厉害怎么办 怀孕干活累着了怎么办 怀孕了上班很累怎么办 孕妇胖的太快怎么办 孕妇长得太快怎么办 眼睛一按吱吱响怎么办 孕期太胖了怎么办啊 人流后子宫复位不好怎么办 怀孕初期有盆腔积液怎么办 怀孕了有盆腔积液怎么办 多囊怀孕不想要怎么办 6个月婴儿大小眼怎么办 健身教练岁数大了以后怎么办 超变战陀玩具手柄坏了怎么办 飓风战魂三陀螺中轴坏了怎么办 怎么办晚安角和铁陀螺 白衣服染上荧光剂了怎么办 指尖陀螺不亮了怎么办 手指陀螺不转了怎么办 月经推迟私处还老是流水怎么办 苹果手机刷机后忘记id密码怎么办 锤基意外怀孕怎么办零6 职场遇到心机婊怎么办 高二会考没过怎么办 保险柜没电了打不开怎么办 保险柜没有电了打不开怎么办 小保险箱没电了怎么办 bim墙的颜色反了怎么办