多线程编程之同步

一.条件变量

线程间的同步还有一种情况:线程A需要等某个条件成立才能继续往下执行,当条件不成立时,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行。在pthread库中通过条件变量(Condition Variable)来阻塞等待一个条件,或者唤醒等待这个条件的线程,条件变量的初始化和销毁函数如下:

返回值:成功返回0,失败返回错误码。

和Mutex的初始化和销毁类似,如果Condition Variable是静态分配的,也可以用宏定义PTHREAD_COND_INITIALIAER初始化,相当于用pthread_cond_init初始化并且参数attr为NULL。 Condition Variable的操作可以用下列函数:

返回值:成功返回0,失败返回错误号

一个Condition Variable 总是和一个Mutex搭配使用的,一个线程可以调用pthread_cond_wait在一个Condition Variable 上阻塞等待,这个函数做已下三步:

(1)释放Mutex

(2)阻塞等待

(3)当被唤醒时,重新获得Mutex并返回

pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程。

二.演示生产者——消费者

生产者生产一个结构体串在链表的表头上,消费者从 表头取走结构体。

代码实现如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 typedef int data_type;
  5 typedef int* data_type_p;
  6 typedef struct _node{
  7         struct _node* _next;
  8         data_type _data;
  9 }node_t,*node_p,**node_pp;
 10 node_p head=NULL;
 11 static pthread_mutex_t lock1=PTHREAD_MUTEX_INITIALIZER;
 12 static pthread_mutex_t lock2=PTHREAD_MUTEX_INITIALIZER;
 13 static pthread_mutex_t lock3=PTHREAD_MUTEX_INITIALIZER;
 14 static pthread_cond_t need_product=PTHREAD_COND_INITIALIZER;
 15 static node_p buy_node(data_type data)
 16 {
 17         node_p tmp=(node_t *)malloc(sizeof(node_t));
 18         if(tmp)
 19         {
 20                 tmp->_data=data;
 21                 tmp->_next=NULL;
 22                 return tmp;
 23         }
 24         return NULL;
 25 }
 26 void init_list(node_pp head)
 27 {
 28         *head=buy_node(0);
 29 }
 30 void push_back(node_p head,data_type data)
 31 {
 32         node_p tmp=buy_node(data);
 33         if(head->_next==NULL)
 34         {
 35                 head->_next=tmp;
 36                 tmp->_next=NULL;
 37         }
 38         else
 39         {
 40                 node_p cur=head;
 41                 while(cur->_next)
 42                 {
 43                         cur=cur->_next;
 44                 }
 45                 cur->_next=tmp;
 46                 tmp->_next=NULL;
 47         }
 48 }
 49 void push_front(node_p head,data_type data)
 50 {
 51         node_p tmp=buy_node(data);
 52         tmp->_next=head->_next;
 53         head->_next=tmp;
 54 }
 55 int pop_front(node_p head,data_type_p buf)
 56 {
 57         if(head->_next==NULL)
 58         {
 59                 *buf = -1;
 60                 return -1;
 61         }
 62         else
 63         {
 64                 node_p tmp=NULL;
 65                 tmp=head->_next;
 66                 *buf=tmp->_data;
 67                 head->_next=tmp->_next;
 68                 tmp->_next=NULL;
 69                 if(tmp)
 70                 {
 71                         free(tmp);
 72                         tmp=NULL;
 73                 }
 74                 return 0;
 75         }
 76 }
 77 void show_list(node_p head)
 78 {
 79         node_p tmp=head->_next;
 80         if(tmp)
 81         {
 82                 printf("%d ",tmp->_data);
 83                 fflush(stdout);
 84                 tmp=tmp->_next;
 85         }
 86         printf("\n");
 87 }
 88 void *product(void *arg)
 89 {
 90         pthread_mutex_lock(&lock2);
 91         int i=0;
 92         while(1)
 93         {
 94                 pthread_mutex_lock(&lock1);
 95                 printf("product success,produce num:%d,,,val is:%d\n", 96                         (int)arg,i);
 97                 push_back(head,i++);            //FIFO
 98                 //push_front(head,i++);        //LIFO
 99                 pthread_mutex_unlock(&lock1);
100                 pthread_cond_signal(&need_product);
101                 sleep(2);
102         }
103         pthread_mutex_unlock(&lock2);
104 }
105 void *consumer(void *arg)
106 {
107         pthread_mutex_unlock(&lock3);
108         data_type buf;
109         while(1)
110         {
111                 pthread_mutex_lock(&lock1);
112                 while(pop_front(head,&buf)==-1)
113                 {
114                         printf("wait**********\n");
115                         pthread_cond_wait(&need_product,&lock1);
116                 }
117                 pthread_mutex_unlock(&lock1);
118                 printf("consumer success,consumer num:%d,,,val is:%d\n",119                         (int)arg,buf);
120                 sleep(5);
121         }
122         pthread_mutex_unlock(&lock3);
123 }
124 int main()
125 {
126         init_list(&head);
127         pthread_t tid1,tid2,tid3,tid4;
128         pthread_create(&tid1,NULL,product,(void*)1);
129         pthread_create(&tid2,NULL,product,(void*)1);
130         pthread_create(&tid3,NULL,consumer,(void*)2);
131         pthread_create(&tid4,NULL,consumer,(void*)2);
132         pthread_join(tid1,NULL);
133         pthread_join(tid2,NULL);
134         pthread_join(tid3,NULL);
135         pthread_join(tid4,NULL);
136         return 0;
137 }

FIFO的运行结果:

LIFO的运行结果:

多生产者——多消费者的运行结果:

时间: 2024-11-09 04:13:05

多线程编程之同步的相关文章

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

多线程编程-----线程同步

同步,永远是多线程编程中最核心和最重要的话题.同步相关的概念比如:临界区,原子操作,以及互斥量等等 总的来说,在多个线程之间采取同步措施,无非是为了让他们更好的协同工作或者维持共享数据的一致性. 1.共享数据的一致性: 多线程程序多以共享数据作为在线程之间传递数据的手段,由于一个进程所拥有的相当一部分虚拟内存地址都可以被该线程中的所有线程所共享.因此这些被共享的数据大多也已内存空间作为载体. 实际上,保证共享数据一致性的最简单且最好的方法,就是使得该数据成为一个常量,但是如果把一个计数器做成常量

多线程编程——线程同步与异步

1.多线程和异步操作的异同 多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性.甚至有些时候我们就认为多线程和异步操作是等同的概念.但是,多线程和异步操作还是有一些区别的.而这些区别造成了使用多线程和异步操作的时机的区别. 2.异步操作的本质 所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础. 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘.光驱的技术规格中都有明确DMA的模式指标,其实网卡.声卡.显卡也是有DMA

java多线程编程——线程同步之同步函数

如何找出线程安全问题: 1.明确那些代码块是多线程运行代码 2.明确共享数据 3.明确多线程运行代码中哪些语句是操作共享数据的 同步函数示例: class Save{ private int sum; public synchronized void add(int n){ sum+=n; System.out.println("sum="+sum); } } class Cus implements Runnable{ private Save b=new Save(); publi

java多线程编程——静态同步函数

//饿汉式,在多线程下是安全的 public class Single { private static final Single s=new Single(); private Single(){}; public static Single getInstance(){ return s; } } //懒汉式,非线程安全,必须使用同步 public class Single { private static Single s=null; private Single(){}; public

Delphi多线程编程之同步读写全局数据

开始研究最重要的多线程读写全局数据了,结合书上的例子,我修改成下面的情况: unit Tst_Thread3U; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type   TForm1 = class(TForm)     Button1: TButton;     Memo1: TMemo;     Button2: TBu

Scratch克隆技术、多线程编程及通讯技术初探

一.引言 Scratch,作为世界流行的青少年编程语言,其对青少年智力的开发及计算思维的培养根本毋庸置疑.既然定位在青少年,那就不能复杂,但是,又要遵循"低门槛,高上限"两个基本特征.让青少年尽快入门的同时,又可以让部分能够深入钻研的同学深刻体会到编程的创造性.复杂性及内在乐趣.而后者,在全国青少年编程竞赛与等级考试中肯定要体现出来--自然也是体现参加者作品创意与难度的所在. Scratch开发者恰当地把握了上述要求与特征:最基础最重要的计算机编程语言特征必须具备,同时又尽可能巧妙地&

线程同步-iOS多线程编程指南(四)-08-多线程

首页 编程指南 Grand Central Dispatch 基本概念 多核心的性能 Dispatch Sources 完结 外传:dispatch_once(上) Block非官方编程指南 基础 内存管理 揭开神秘面纱(上) 揭开神秘面纱(下) iOS多线程编程指南 关于多线程编程 线程管理 Run Loop 线程同步 附录 Core Animation编程指南 Core Animation简介 基本概念 渲染架构 几何变换 查看目录 中文手册/API ASIHTTPRequest Openg

VC++多线程编程-线程间的通信和线程同步

引用:http://blog.csdn.net/zjc0888/article/details/7372258 线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明. 使用全局变量进行通信 由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量.对于标准类型