生产者消费者问题(线程同步)

//一个同步程序,生产者向一个缓冲区(定义为三个字节)中写入数据,消费者从中提取数

//据,如果缓冲区中没有数据,那么consumer只好wait,进入等待状态,当另一个线程(也就是

//生产者)向缓冲区中写入数据猴,执行了Monitor.pulse,唤醒了consumer的等待,开始读取

//数据.反之,当producer写入数据的时候,如果缓冲区已满,那么只好进入等待状态,当另一

//个线程(也就是消费者)从中读取了数据,缓冲区有了空间,那么消费者执行

//Monitor.pulse,唤醒生产者,继续写入数据.

//程序使用了lock来锁定共享数据区,而不是使用Monitor.enter和Monitor.exit,因为你可

//能很容易忘记enter后exit掉,而lock则是隐式的执行了exit,所以建议用lock.

//当然,在程序执行的过程中,因为是线程,所以执行结果是不可再现的!!每次可能执行的顺

//序有很多种!!


//定义了四个类:

//第一个类LetSynchronized,主要用来存取数据,并且在存取的时候,加上了共享锁.

//第二个类Producer,生产者,调用一个LetSynchronized类的实例的setBuffer方法来存放

//数据.

//第三个类Consumer,消费者, 调用一个LetSynchronized类的实例的getBuffer方法来存放

//数据.

//第四个类ThreadStart,测试类,也是这个cs中的启动类,定义了LetSynchornized实例,然

//后传递给了Producer和Consumer,然后定义了两个线程,线程启动的是Producer

//的produce方法和Consumer的consume方法,最后启动这两个线程.


using System;

using System.Threading;

//LetSynchronized用来存放和取出缓冲区变量

public class LetSynchronized

{

private int[] buffer={-1,-1,-1};

//定义了只有三个字节的缓冲区

private int bufferCount=0;

//确认缓冲区内已放数值的个数

private int readLocation=0,writeLocation=0;

//确定读写的位置

public LetSynchronized()

{

}

public int getBuffer()

{

lock(this)

//加上了共享锁

{

if(bufferCount==0)

{

Console.WriteLine("缓冲区无数据,消费者无法读取");

Monitor.Wait(this);

}

//判断如果缓冲区内无内容,则Consumer进入wait状态,并且释放对象锁

int readValue=buffer[readLocation];

bufferCount--;

//已经从缓冲区读取了内容,所以bufferCount要进行自减.

readLocation=(readLocation+1)%buffer.Length;

//求余的目的是为了循环使用缓冲区

Monitor.Pulse(this);

//通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.

return readValue;

//返回给consumer取出的数值

}

}

public void setBuffer(int writeValue) //将数据放入缓冲区

{

lock(this)

{//锁住共享数据区

if(bufferCount==buffer.Length)

{

Console.WriteLine("缓冲区!");

Monitor.Wait(this);

}

//如果缓冲区已满,那么进入waitsleepjoin状态

buffer[writeLocation]=writeValue;

//向缓冲区写入数据

bufferCount++;

//自加,代表缓冲区现在到底有几个数据

writeLocation=(writeLocation+1)%buffer.Length;

//用%实现缓冲区的循环利用

Monitor.Pulse(this);

//唤醒waitSleepJoin状态的进程,到started状态

}//使用lock隐式的释放了共享锁

}

}

public class Producer //生产者类,向缓冲区中放入数据

{

LetSynchronized shared;

//定义了同步变量

public Producer(LetSynchronized sharedLocation)

{

shared=sharedLocation;

}

//此处构造函数的作用是在启动类中调用Producer的时候,把启动类中定义的sharedLocation传过来

public void produce()//定义生产过程

{

for(int count=1;count<=5;count++)

{

shared.setBuffer(count);

Console.WriteLine("生产者向缓冲区中写入 "+ count);

}

//将数据放入缓冲区

string name=Thread.CurrentThread.Name;

//得到当前线程的名字

Console.WriteLine(name+"done producing");

//此线程执行完毕

}

}

public class Consumer//定义消费者类

{

private int value;

LetSynchronized shared;

//定义同步变量

public Consumer(LetSynchronized sharedLocation)

{

shared=sharedLocation;

}

//定义构造函数,负责传递启动类中的shared

public void consume()

{

for(int count=1;count<=5;count++)

{

value=shared.getBuffer();

Console.WriteLine("消费者从缓冲中读取了数据 "+value);

}

//从缓冲区中循环读取

string name=Thread.CurrentThread.Name;

//取得当前线程的名字

Console.WriteLine(name+"done consuming");

}

}

public class ThreadTest //设置为启动类

{

public static void Main()

{

LetSynchronized shared=new LetSynchronized();

Producer producer1=new Producer(shared);

Consumer consumer1=new Consumer(shared);

//初始化了生产者和消费者,并且把shared参数传递了过去

Thread producerThread = new Thread(new ThreadStart (producer1.produce));

producerThread.Name="生产者";

//定义了一个producerThread线程,new Thread是构造Thread

//后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produce

Thread consumerThread = new Thread(new ThreadStart (consumer1.consume));

consumerThread.Name="消费者";

//同上

producerThread.Start();

consumerThread.Start();

//启动这两个线程

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者同步问题是一个经典的线程同步问题,Linux可以使用线程和互斥锁来实现。 具体实现思路如下: 1. 定义一个固定大小的缓冲区,用来存放生产者生产的数据。 2. 定义两个线程函数,一个生产者线程一个为消费者线程。 3. 生产者线程向缓冲区生产数据,如果缓冲区已经满了,就等待消费者线程消费数据。 4. 消费者线程从缓冲区取出数据,如果缓冲区为空,就等待生产者线程生产数据。 5. 生产者和消费者线程之间通过互斥锁来保证同步。 下面是一个简单的 Linux C 代码示例: ```c #include <stdio.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0; int out = 0; int count = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t full = PTHREAD_COND_INITIALIZER; pthread_cond_t empty = PTHREAD_COND_INITIALIZER; void *producer(void *arg) { int i; for (i = 0; i < 20; i++) { pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) { pthread_cond_wait(&empty, &mutex); } buffer[in] = i; in = (in + 1) % BUFFER_SIZE; count++; pthread_cond_signal(&full); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } void *consumer(void *arg) { int i, data; for (i = 0; i < 20; i++) { pthread_mutex_lock(&mutex); while (count == 0) { pthread_cond_wait(&full, &mutex); } data = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; pthread_cond_signal(&empty); pthread_mutex_unlock(&mutex); printf("Consumer get data: %d\n", data); } pthread_exit(NULL); } int main(int argc, char *argv[]) { pthread_t producer_thread, consumer_thread; pthread_create(&producer_thread, NULL, producer, NULL); pthread_create(&consumer_thread, NULL, consumer, NULL); pthread_join(producer_thread, NULL); pthread_join(consumer_thread, NULL); return 0; } ``` 在这个示例,我们定义了一个大小为 10 的缓冲区,然后创建了一个生产者线程一个消费者线程生产者线程会生产 20 个数据,消费者线程会消费这些数据并输出。两个线程之间通过互斥锁和条件变量进行同步,确保生产者和消费者之间的数据交换是正确的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值