读书人

C# 线程同步有关问题

发布时间: 2013-10-25 14:36:53 作者: rapoo

C# 线程同步问题

在现实生活中,假设有一个生产者和一个消费者。生产者生成货物存储在货物栈中,消费者从货物栈中取货物。假设生产者的生成速度超过消费者消费速度,则货物栈会在某一个时刻被装满,此时生产者若继续生产会导致两种情况:货物栈溢出;货物栈中已有货物被替换。假设消费者的消费速度超过生产者的生产速度,则货物栈会在某一个时刻被取空,此时消费者若继续消费会导致消费者得到的货物为空。实现生产者消费者同步的目的在于使得生产者按顺序生产,消费者按顺序消费,当生产速度过快时,暂停生产;当消费速度过快时,暂停消费。生产者和消费者的行为需要一个管理员来控制。

使用两个线程来分别模拟生产者和消费者。使用 Monitor 来模拟管理员。管理员在生产过剩时告诉生产者暂停生产,消费过剩时告诉消费者暂停消费。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace MultiThread{    class Problem    {        static int[] buffers=new int[3];        static int readLocation=0;        static int writeLocation = 0;        static object locker=new object();        static int blankCount = 3;        private int Buffer         {            get             {                lock (locker)                {                    if (blankCount >= 3)                    {                        Console.WriteLine("buffers are all empty now! Consumer waits!");                        Monitor.Wait(locker);                    }                    readLocation = readLocation % 3;                    int buffer = buffers[readLocation];                    buffers[readLocation] = 0;                    readLocation++;                    blankCount++;                    Monitor.Pulse(locker);                    return buffer;                }            }            set            {                lock (locker)                {                    if (blankCount <= 0)                    {                        Console.WriteLine("buffers are all full now! Producer waits!");                        Monitor.Wait(locker);                     }                    writeLocation = writeLocation % 3;                    buffers[writeLocation] = value;                    writeLocation++;                    blankCount--;                    Monitor.Pulse(locker);                }            }        }        void Produce()        {                        for (int i = 0; i < 11; i++)            {                                                lock (locker)                {                    this.Buffer = i+1;                    Console.WriteLine("Produer has produce a " + (i+1) + " in buffers");                    Thread.Sleep(1000);                }                            }        }        void Consume()        {                        for (int i = 0; i < 11; i++)            {                                                lock (locker)                {                    Console.WriteLine("Consumber has consume a " + this.Buffer + " from buffers");                    Thread.Sleep(1000);                }                            }        }        static void Main(string[] args)        {            Problem p = new Problem();            Thread producer = new Thread(p.Produce);            Thread consumer = new Thread(p.Consume);            producer.Name = "producer";            producer.Start();            consumer.Name = "consumer";            consumer.Start();            Console.ReadKey();        }    }}

锁对象并不保证线程间会同步。生产者消费者都拥有锁,锁就没有作用,线程执行时会忽略锁的存在继续执行被锁住的代码。只有管理员通过这个锁来通知生产者和消费者时,这个锁才会起到阻止线程执行的作用。锁的目的只是保证这个代码块中的变量的值是最新的,但不保证别的线程不会去修改这个变量。锁可以是任意对象,但要保证消费和生产这一对操作所使用的锁对象是同一个对象。
1. Memory barriers

http://stackoverflow.com/questions/6581848/memory-barrier-generators

2. Threading in C#

http://www.albahari.com/threading/

1楼changtianshuiyue昨天 17:35
对于锁不保证其他线程不修改锁内变量:n1. 进入锁后,意味着线程已经获得该锁,则只有该线程能够运行锁内代码,能修改锁内变量,亦即保证锁内部代码原子执行。n2. 若一个锁在一个方法内部,而方法内还有除锁代码外其他代码,由于方法不能保证原子执行,则在获得锁之前和释放锁之后会导致其他线程修改锁内变量。

读书人网 >编程

热点推荐