码迷,mamicode.com
首页 > 编程语言 > 详细

线程同步与互斥(POSIX信号量——环形数组实现生产者消费者模型)

时间:2016-04-22 16:41:43      阅读:270      评论:0      收藏:0      [点我收藏+]

标签:模型   生产者   消费者   信号量   环形数组   

Semaphore(信号量)


Mutex变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源,加锁时获得该资源,将Mutex减到0,表示不再有可用资源,解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源。


信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1。如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同!


POSIX semaphore库函数,这种信号量不仅可用于同一进程的线程间同步,也可用于不同进程间的同步。



有关函数:


技术分享


单生产者但消费者模型:

代码说明:

1.push()和pop()的数据(datatype)本篇用的是基本类型,如果是自定义类型的话,需要实现赋值运算符的重载

2.数组实际上是线性的,内存中并没有环形数组,我们定义了一个固定大小的数组,当数组的最后一个元素也被填上数据时,检查数组的第一个元素(下标为0的元素)是否已经被消费者读过,如果已经读过,那么生产者就可以继续放数据,当数组满时(即数组中的元素一个也没有被消费者读),生产者会等待。

3.sem_init()初始化两个信号量sem_p(控制生产者)和sem_c(控制消费者),pshared为0时,表示信号量用于同一进程的线程间同步

 sem_destroy()使两个信号量回到初始化前的状态

 sem_wait() 可以获得资源,相当于P操作,把给定信号量减一

 sem_post() 可以释放资源,相当于V操作,进行加一操作

 当信号量的值为0时,sem_wait()会将进程挂起等待,sem_trywait()不会将进程挂起


代码实现:

ring.cpp

#include <iostream>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

#define SEM_PRO 20
#define SEM_CON 0
#define SIZE SEM_PRO

typedef int datatype; 

datatype ring[SIZE];//数组的定义
datatype pro,con;

sem_t sem_p;//product
sem_t sem_c;//consumer


void init_ring(datatype (*ring)[SIZE])
{
    pro=0;
    con=0;
 }

datatype& push(datatype &data,int index)
{
    ring[pro++]=data;
    datatype tmp=ring[pro-1];
    pro%=SIZE;
    return tmp;
}

datatype& pop(int index)
{
    con++;
    datatype tmp=ring[con-1];
    con%=SIZE;
    return tmp;
}

void* product(void* arg)
{
    while(1){
        datatype data=rand()%50;
        sem_wait(&sem_p);
        datatype val=push(data,pro);
        cout<<"product done...,val is:"<<val<<endl;
        sem_post(&sem_c);
        sleep(1);
    }
}

void* consumer(void* arg)
{
    while(1){
        sem_wait(&sem_c);
        datatype val=pop(con);
        cout<<"consumer done...,val is:"<<val<<endl;
        sem_post(&sem_p);
        sleep(8);
    }
}

int main()
{
    init_ring(&ring);

    sem_init(&sem_p,0,SEM_PRO);
    sem_init(&sem_c,0,0);

    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,product,NULL);
    pthread_create(&tid2,NULL,consumer,NULL);

    sem_destroy(&sem_p);
    sem_destroy(&sem_c);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    return 0;
}

Makefile

ring:ring.cpp
    g++ -o $@ $^ -lpthread

.PHONY:clean
clean:
    rm -f ring


下面两次运行生产者和消费者的速度有所变化,导致运行结果不同

第一次运行结果:

技术分享

第二次运行结果:

技术分享


多生产者多消费者模型:(实际上和单生产者单消费者一样,只多加了6行线程创建和等待的代码)

#include <iostream>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

#define SEM_PRO 20
#define SEM_CON 0
#define SIZE SEM_PRO

typedef int datatype;

datatype ring[SIZE];
datatype pro,con;

sem_t sem_p;//product
sem_t sem_c;//consumer

void init_ring(datatype (*ring)[SIZE])
{
    pro=0;
    con=0;
}

datatype& push(datatype &data,int index)
{
    ring[pro++]=data;
    datatype tmp=ring[pro-1];
    pro%=SIZE;
    return tmp;
}

datatype& pop(int index)
{
    con++;
    datatype tmp=ring[con-1];
    con%=SIZE;
    return tmp;
}

void* product(void* arg)
{
    while(1){
        datatype data=rand()%50;
        sem_wait(&sem_p);
        datatype val=push(data,pro);
        sem_wait(&sem_p);
        datatype val=push(data,pro);
        cout<<"product"<<(int)arg<<" done...,val is:"<<val<<endl;
        sem_post(&sem_c);
        sleep(1);
    }
}

void* consumer(void* arg)
{
    while(1){
        sem_wait(&sem_c);
        datatype val=pop(con);
        cout<<"consumer"<<(int)arg<<" done...,val is:"<<val<<endl;
        sem_post(&sem_p);
        sleep(3);
    }
}

int main()
{
    init_ring(&ring);

    sem_init(&sem_p,0,SEM_PRO);
    sem_init(&sem_c,0,0);

    pthread_t tid1,tid2,tid3;
    pthread_create(&tid1,NULL,product,(void*)1);
    pthread_create(&tid2,NULL,product,(void*)2);
    pthread_create(&tid3,NULL,product,(void*)3);

    pthread_t tid4,tid5;
    pthread_create(&tid4,NULL,consumer,(void*)4);
    pthread_create(&tid5,NULL,consumer,(void*)5);

    sem_destroy(&sem_p);
    sem_destroy(&sem_c);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);
    pthread_join(tid4,NULL);
    pthread_join(tid5,NULL);

    return 0;
}

运行结果:

技术分享

本文出自 “零蛋蛋” 博客,请务必保留此出处http://lingdandan.blog.51cto.com/10697032/1766740

线程同步与互斥(POSIX信号量——环形数组实现生产者消费者模型)

标签:模型   生产者   消费者   信号量   环形数组   

原文地址:http://lingdandan.blog.51cto.com/10697032/1766740

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!