线程同步:何时互斥锁不够,还需要条件变量?

http://www.blogjava.net/fhtdy2004/archive/2009/07/05/285519.html

线程同步:何时互斥锁不够,还需要条件变量?

很显然,pthread中的条件变量与Java中的wait,notify类似

假设有共享的资源sum,与之相关联的mutex 是lock_s.假设每个线程对sum的操作很简单的,与sum的状态无关,比如只是sum++.那么只用mutex足够了.程序员只要确保每个线程操作前,取得lock,然后sum++,再unlock即可.每个线程的代码将像这样add()
{
  pthread_mutex_lock(lock_s);
  sum++;
  pthread_mutex_unlock(lock_s);
}

  如果操作比较复杂,假设线程t0,t1,t2的操作是sum++,而线程t3则是在sum到达100的时候,打印出一条信息,并对sum清零.这种情况下,如果只用mutex, 则t3需要一个循环,每个循环里先取得lock_s,然后检查sum的状态,如果sum>=100,则打印并清零,然后unlock.如果sum<100,则unlock,并sleep()本线程合适的一段时间.

 这个时候,t0,t1,t2的代码不变,t3的代码如下
  print()
  {
    while (1)
    {
      pthread_mutex_lock(lock_s);
      if(sum<100)
      {
        printf(“sum reach 100!”);
        pthread_mutex_unlock(lock_s);
      }
      else
      {
        pthread_mutex_unlock(lock_s);
        my_thread_sleep(100);
        return OK;
      }
    }
  }

这种办法有两个问题
  1) sum在大多数情况下不会到达100,那么对t3的代码来说,大多数情况下,走的是else分支,只是lock和unlock,然后sleep().这浪费了CPU处理时间.
  2) 为了节省CPU处理时间,t3会在探测到sum没到达100的时候sleep()一段时间.这样却又带来另外一个问题,亦即t3响应速度下降.可能在sum到达200的时候,t3才会醒过来.
  3) 这样,程序员在设置sleep()时间的时候陷入两难境地,设置得太短了节省不了资源,太长了又降低响应速度.真是难办啊!

  这个时候,condition variable内裤外穿,从天而降,拯救了焦头烂额的你.

  你首先定义一个condition variable.
  pthread_cond_t cond_sum_ready=PTHREAD_COND_INITIALIZER;

  t0,t1,t2的代码只要后面加两行,像这样
  add()
  {
    pthread_mutex_lock(lock_s);
    sum++;
    pthread_mutex_unlock(lock_s);
    if(sum>=100)
    pthread_cond_signal(&cond_sum_ready);
  }
  而t3的代码则是
  print
  {
    pthread_mutex_lock(lock_s);
    while(sum<100)
    pthread_cond_wait(&cond_sum_ready, &lock_s);
    printf(“sum is over 100!”);
    sum=0;
    pthread_mutex_unlock(lock_s);
    return OK;
  }

注意两点:
  1) 在thread_cond_wait()之前,必须先lock相关联的mutex, 因为假如目标条件未满足,pthread_cond_wait()实际上会unlock该mutex, 然后block,在目标条件满足后再重新lock该mutex, 然后返回.--这点非常重要

  2) 为什么是while(sum<100),而不是if(sum<100) ?这是因为在pthread_cond_signal()和pthread_cond_wait()返回之间,有时间差,假设在这个时间差内,还有另外一个线程t4又把sum减少到100以下了,那么t3在pthread_cond_wait()返回之后,显然应该再检查一遍sum的大小.这就是用while的用意

线程同步:何时互斥锁不够,还需要条件变量?,布布扣,bubuko.com

时间: 2024-12-26 11:40:59

线程同步:何时互斥锁不够,还需要条件变量?的相关文章

LinuxC线程pthread线程同步进程同步-互斥量、信号量、条件变量、读写锁、文件锁

1. 同步概念 2. 线程同步 3. 进程同步 4. 生产者消费者模型 5. 哲学家问题 原文地址:https://www.cnblogs.com/yongfengnice/p/12116954.html

互斥锁,信号量,条件变量,读写锁

互斥锁 互斥锁的特性: 1. 原子性:当有一个线程成功拿到了这个锁,其他线程都无法在相同的时间拿到这个锁 2. 唯一性:在一个线程拿到锁的这段时间,只有当这个线程把锁释放掉,其他的线程才有可能拿到 3. 非繁忙等待性:如果一个线程已经锁定了一个互斥量,第二个线程又视图去拿到这个锁的前线,则第二个锁将被挂起,等待第一个线程对互斥量解锁位置,同时第二个线程获取锁,继续往下执行 pthread_mutex_init pthread_mutex_lock pthread_mutex_trylock pt

APUE学习笔记——11 线程同步、互斥锁、自旋锁、条件变量

线程同步 同属于一个进程的不同线程是共享内存的,因而在执行过程中需要考虑数据的一致性. 假设:进程有一变量i=0,线程A执行i++,线程B执行i++,那么最终i的取值是多少呢?似乎一定是i=2:其实不然,如果没有考虑线程同步,i的取值可能是1.我们先考虑自加操作的过程:a,首先将内存中i的值copy到寄存器:b,对寄存器中i的copy进行自加:c,将寄存器中自加的结果返回到内存中.回到例子,如果线程A执行完abc三个步骤,线程B在执行者三个步骤,那么结果就应该为2.但是自加不是原子操作,假如执行

互斥锁、信号量、条件变量的区别

来自:http://blog.chinaunix.net/space.php?uid=23061624&do=blog&cuid=2127853 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在哪里).而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源.比如对全局变量的访问,有时要加锁,操作完了,在解锁.有

线程同步(互斥锁与信号量的作用与区别)

“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源.比如对全局变量的访问,有时要加锁,操作完了,在解锁.有的时候锁和信号量会同时使用的” 也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后

Linux 多线程同步机制:互斥量、信号量、条件变量

互斥量:互斥量提供对共享资源的保护访问,它的两种状态:lock和unlock,用来保证某段时间内只有一个线程使用共享资源,互斥量的数据类型是pthread_mutex_t主要涉及函数:pthread_mutex_lock() pthread_mutex_trylock() pthread_mutex_unlock()Pthreaf_mutex_init() pthread_mutex_destroy()lock与unlock之间所锁定的区域为临界区域(如果只加锁不解锁程序会阻塞等待)信号量:信号

线程&mdash;同步之互斥锁

线程互斥:实质某一资源同时只允许一个访问者对其进行访问,具有唯一性和排他性. import threading import time g_lock = threading.Lock() def func(): global tmp global g_lock g_lock.acquire() for i in range(20,40): tmp = i] print "%s:tmp = %d"%(threading.currentThread(),getName(),tmp) tim

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,

一起talk C栗子吧(第一百一十六回:C语言实例--线程同步之互斥量二)

各位看官们,大家好,上一回中咱们说的是线程同步之信号量的例子,这一回咱们继续说该例子.闲话休提,言归正转.让我们一起talk C栗子吧! 我们在上一回中详细介绍了互斥量相关函数的用法,这一回中,我们介绍如何使用这些函数来操作互斥量. 下面是详细的操作步骤: 1.定义一个互斥量A,用来同步线程: 2.在创建线程的进程中使用pthread_mutex_init函数初始化互斥量,互斥量的属性使用默认值: 3.在读取数据的线程中读取数据,首先使用pthread_mutex_lock函数对互斥量A进行加锁