条件变量提供另一种多线程同步的方法。互斥量通过控制对共享数据的访问来同步任务。条件变量可以根据数据的值来同步任务。条件变量是当一个事件发生时发送信号的信号量。一旦事件发生,可能会有多个线程在等待信号,条件变量通常用于对操作的顺序进行同步。使用条件变量对多线程进行同步时,条件变量和互斥量得同时使用。知道这些大概知识,本文将重点探讨怎么使用条件变量进行同步,结构分为三个部分,第一部分给出代码示例,第二部分对代码进行讲解,第三部分给出运行结果。

一、代码示例

#include "StdAfx.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define NUM_THREADS  3
#define TCOUNT 10
#define COUNT_LIMIT 12

int     count = 0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;

void *inc_count(void *t)
{
  int i;
  long my_id = (long)t;

  for (i=0; i < TCOUNT; i++) {
    pthread_mutex_lock(&count_mutex);
    count++;

    /*
    Check the value of count and signal waiting thread when condition is
    reached.  Note that this occurs while mutex is locked.
    */
    if (count == COUNT_LIMIT) {
      printf("inc_count(): thread %ld, count = %d  Threshold reached. ",
             my_id, count);
      pthread_cond_signal(&count_threshold_cv);
      printf("Just sent signal.\n");
      }
    printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
	   my_id, count);
    pthread_mutex_unlock(&count_mutex);

    /* Do some work so threads can alternate on mutex lock */
    Sleep(10);
    }
  pthread_exit(NULL);
  return(NULL);
}

void *watch_count(void *t)
{
  long my_id = (long)t;

  printf("Starting watch_count(): thread %ld\n", my_id);

  /*
  Lock mutex and wait for signal.  Note that the pthread_cond_wait routine
  will automatically and atomically unlock mutex while it waits.
  Also, note that if COUNT_LIMIT is reached before this routine is run by
  the waiting thread, the loop will be skipped to prevent pthread_cond_wait
  from never returning.
  */
  pthread_mutex_lock(&count_mutex);
  while (count < COUNT_LIMIT) {
    printf("watch_count(): thread %ld Count= %d. Going into wait...\n", my_id,count);
    pthread_cond_wait(&count_threshold_cv, &count_mutex);
    printf("watch_count(): thread %ld Condition signal received. Count= %d\n", my_id,count);
    printf("watch_count(): thread %ld Updating the value of count...\n", my_id,count);
    count += 125;
    printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
    }
  printf("watch_count(): thread %ld Unlocking mutex.\n", my_id);
  pthread_mutex_unlock(&count_mutex);
  pthread_exit(NULL);
  return(NULL);
}

int main(int argc, char *argv[])
{
  int i, rc;
  long t1=1, t2=2, t3=3;
  pthread_t threads[3];
  pthread_attr_t attr;

  /* Initialize mutex and condition variable objects */
  pthread_mutex_init(&count_mutex, NULL);
  pthread_cond_init (&count_threshold_cv, NULL);

  /* For portability, explicitly create threads in a joinable state */
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_create(&threads[0], &attr, watch_count, (void *)t1);
  pthread_create(&threads[1], &attr, inc_count, (void *)t2);
  pthread_create(&threads[2], &attr, inc_count, (void *)t3);

  /* Wait for all threads to complete */
  for (i = 0; i < NUM_THREADS; i++) {
    pthread_join(threads[i], NULL);
  }
  printf ("Main(): Waited and joined with %d threads. Final value of count = %d. Done.\n",
          NUM_THREADS, count);

  /* Clean up and exit */
  pthread_attr_destroy(&attr);
  pthread_mutex_destroy(&count_mutex);
  pthread_cond_destroy(&count_threshold_cv);
  pthread_exit (NULL);

}

二、代码讲解

int     count = 0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;

定义全局变量计数器,互斥量和条件变量

void *inc_count(void *t)
{
  int i;
  long my_id = (long)t;

  for (i=0; i < TCOUNT; i++) {
    pthread_mutex_lock(&count_mutex);
    count++;

    if (count == COUNT_LIMIT) {
      printf("inc_count(): thread %ld, count = %d  Threshold reached. ",
             my_id, count);
      pthread_cond_signal(&count_threshold_cv);
      printf("Just sent signal.\n");
      }
    printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
	   my_id, count);
    pthread_mutex_unlock(&count_mutex);

    Sleep(10);
    }
  pthread_exit(NULL);
  return(NULL);
}

inc_count()函数是线程2和3执行的任务,每次for循环调用pthread_mutex_lock锁住互斥量,从而对全局变量进行计数,当计数达到一定条件,调用pthread_cond_signal函数发送条件变量,然后对互斥量进行解锁,为了另一个线程有充足时间锁住互斥量,让本线程休眠一段时间,最后退出线程。

void *watch_count(void *t)
{
  long my_id = (long)t;

  printf("Starting watch_count(): thread %ld\n", my_id);

  pthread_mutex_lock(&count_mutex);
  while (count < COUNT_LIMIT) {
    printf("watch_count(): thread %ld Count= %d. Going into wait...\n", my_id,count);
    pthread_cond_wait(&count_threshold_cv, &count_mutex);
    printf("watch_count(): thread %ld Condition signal received. Count= %d\n", my_id,count);
    printf("watch_count(): thread %ld Updating the value of count...\n", my_id,count);
    count += 125;
    printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
    }
  printf("watch_count(): thread %ld Unlocking mutex.\n", my_id);
  pthread_mutex_unlock(&count_mutex);
  pthread_exit(NULL);
  return(NULL);
}

watch_count函数是线程1执行的函数,该线程主要是完成接受发送的条件变量。首先,调用pthread_mutex_lock函数锁住互斥量我;为了使等待时间在有限范围内,使用满足条件的while循环,因为假如count大于条件,那么等待的时间将是无穷无尽的;调用pthread_cond_wait函数接受条件变量,直到接受到条件变量,才执行下一步程序;接受完条件变量后,对互斥量进行解锁,最后退出线程。

 int i, rc;
 long t1=1, t2=2, t3=3;
 pthread_t threads[3];
 pthread_attr_t attr;

 pthread_mutex_init(&count_mutex, NULL);
 pthread_cond_init (&count_threshold_cv, NULL);

定义程序所需变量,pthread_t变量以及属性对象attr;初始化全局互斥量,初始化全局条件变量。

  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_create(&threads[0], &attr, watch_count, (void *)t1);
  pthread_create(&threads[1], &attr, inc_count, (void *)t2);
  pthread_create(&threads[2], &attr, inc_count, (void *)t3);

  for (i = 0; i < NUM_THREADS; i++) {
    pthread_join(threads[i], NULL);
  }
  printf ("Main(): Waited and joined with %d threads. Final value of count = %d. Done.\n",
          NUM_THREADS, count);

初始化属性对象,并将属性对象设置为可结合的,然后使用该属性对象创建三个线程,分别执行watch_count和inc_count函数,最后结合所有的线程。

  pthread_attr_destroy(&attr);
  pthread_mutex_destroy(&count_mutex);
  pthread_cond_destroy(&count_threshold_cv);
  pthread_exit (NULL);

销毁属性对象、互斥量和条件变量,退出线程。

三、运行结果

学习pthreads,使用条件变量进行多线程之间的同步的更多相关文章

  1. 学习pthreads,创建和终止多线程

    更CPU多线程编程,通过笔者的研究发现,,pthreads使用日趋广泛.它是螺纹POSIX标准,它定义了一组线程的创建和操作API. 配置环境见上博客文章.配置环境后,只需要加入#include &l ...

  2. Linux Qt使用POSIX多线程条件变量、互斥锁(量)

    今天团建,但是文章也要写.酒要喝好,文要写美,方为我辈程序员的全才之路.嘎嘎 之前一直在看POSIX的多线程编程,上个周末结合自己的理解,写了一个基于Qt的用条件变量同步线程的例子.故此来和大家一起分 ...

  3. 条件变量signal与unlock的顺序

    编写同步队列时,有用到条件变量,对操作队列的线程进行同步.当队列为空时,允许get线程挂起,直到add线程向队列添加元素并通过唤醒条件变量,get线程继续向下运行.条件变量在多线程程序中用来实现“等待 ...

  4. linux线程同步(2)-条件变量

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  5. boost库(条件变量)

    1相关理念 (1)类名 条件变量和互斥变量都是boost库中被封装的类. (2)条件变量 条件变量是thread库提供的一种等待线程同步的机制,可实现线程间的通信,它必须与互斥量配合使用,等待另一个线 ...

  6. posix 条件变量与互斥锁 示例生产者--消费者问题

    一.posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行. 在pthr ...

  7. linux条件变量

    条件变量用于线程之间的通信,和互斥锁一起使用.条件变量用于及时通知等待的线程条件的变化,使线程不至于错过变化. 考虑下面的情况,有AB两个线程对index这个全局变量进行++,一个线程C用于判断,in ...

  8. c++11中的线程、锁和条件变量

    void func(int i, double d, const string& s) { cout << i << ", " << d ...

  9. [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

    一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...

随机推荐

  1. JS中的DOM— —节点以及操作

    DOM操作在JS中可以说是非常常见了吧,很多网页的小功能的实现,比如一些元素的增删操作等都可以用JS来实现.那么在DOM中我们需要知道些什么才能完成一些功能的实现呢?今天这篇文章就先简单的带大家入一下 ...

  2. 谈谈Circuit Breaker在.NET Core中的简单应用

    前言 由于微服务的盛行,不少公司都将原来细粒度比较大的服务拆分成多个小的服务,让每个小服务做好自己的事即可. 经过拆分之后,就避免不了服务之间的相互调用问题!如果调用没有处理好,就有可能造成整个系统的 ...

  3. Ubuntu 16.04 + ROS Kinetic 机器人操作系统学习镜像分享与使用安装说明

    Ubuntu 16.04 + ROS Kinetic 镜像分享与使用安装说明 内容概要:1 网盘文件介绍  2 镜像制作  3 系统使用与安装 ---- 祝ROS爱好者和开发者新年快乐:-) ---- ...

  4. Bootstrap3 代码-代码块

    多行代码可以使用 <pre> 标签.为了正确的展示代码,注意将尖括号做转义处理. <p>Sample text here...</p> <pre>< ...

  5. Java对象的创建 —— new之后JVM都做了什么?

    Java对象创建过程 1. 类加载检查 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没 ...

  6. Activtiy完全解析(三、View的显示过程measure、layout、draw)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52840065 本文出自:[openXu的博客]   在Activity完全解析的第一篇文章A ...

  7. Sublime text 添加lua

    tools ->build system->new build system... 输入: { "cmd": ["C:\\lua\\lua53.exe&quo ...

  8. 自定义一个View作为弹出对话框

    public void dialog(){ //获得布局对象 View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialo ...

  9. linux 最大文件描述符

    Linux对应用程序能打开的的最大文件描述符数量有两个层次的限制:用户级限制和系统级限制. 用户级限制是指目标用户运行的所有进程总共能打开的文件描述符数. 系统级的限制是指所有用户总共能打开的文件描述 ...

  10. 使用OpenCV读、操作、写图像并与bash合作对某个目录下所有图像进行类似处理

    我门要对某个目录下所有图像文件进行统一处理,如果图像的数量过多,那么手动地一张张处理就会显得有些麻烦.本文使用OpenCV和bash来完成我们指定的任务. 任务 将目录A下的所有统一格式的jpg图像变 ...