欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#多线程的同步与通信

程序员文章站 2023-11-04 11:39:28
C#中使用lock和Monitor控制多线程对资源的使用,最常见的生产者和消费者问题就是多线程同步和通信的经典例子。了解C#多线程的同步与通信。 一、关于lock和Monitor lock可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其它 ......

c#中使用lock和monitor控制多线程对资源的使用,最常见的生产者和消费者问题就是多线程同步和通信的经典例子。了解c#多线程的同步与通信。

一、关于lock和monitor

lock可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其它线程必须等待。格式定义如下:

lock(expression) statement_block

 expression代表要跟踪的对象,通常是引用。一般地,如果想保护一个类的实例,使用this;如果保护一个静态变量(如互斥代码段在一个静态方法内部),使用类名就可以了。而statement_block就是互斥段的代码。

monitor用于多线程公用一个对象时使线程共享资源的方案。monitor必须和一个具体的对象相关联。

二、生产者和消费者问题

假设两个线程同时维护一个队列,如果一个线程对队列中更新元素,而另外一个线程从队列中获取元素,那么我们称更新元素的线程为生产者,称获取元素的线程为消费者。

1、被操作对象

C#多线程的同步与通信
   /// <summary>;
    /// 被操作对象
    /// </summary>;
    public class counter
    {
        //更新和读取的数字
        private int numberofcounter;
        //读操作可执行标记,可以防止死锁的发生
        private bool readflag = false;
 
        public void read()
        {
            //锁定后,其它读操作等待这一次读操作完成
            lock (this)
            {
                //第一次之行为flase,进入等待
                if (!readflag)
                {
                    try
                    {
                        //进入等待读,另一个线程写
                        monitor.wait(this);
                    }
                    catch (exception ex)
                    {
                        console.writeline(ex);
                    }
                }
 
                console.writeline("消费(获取): {0}", numberofcounter);
 
                //重置,消费已经完成
                readflag = false;
                monitor.pulse(this);
            }
        }
 
        public void write(int number)
        {
            //锁定后,其它写操作等待这一次写操作完成
            lock (this)
            {
                //第一次readflag为flase,跳过执行下边的写
                //如果当前正在读,等待读操作执行monitor.pulse
                if (readflag)
                {
                    try
                    {
                        monitor.wait(this);
                    }
                    catch (exception ex)
                    {
                        console.writeline(ex);
                    }
                }
                numberofcounter = number;
                console.writeline("生产(更新): {0}", numberofcounter);
 
                //重置,生产已经完成
                readflag = true;
 
                //同步通过等待pulse来完成
                monitor.pulse(this);
            }
        }
    }
C#多线程的同步与通信

2、生产者和消费者

C#多线程的同步与通信
   /// <summary>;
    /// 生产者
    /// </summary>
    public class counterwrite
    {
        counter counter;
        //生产者生产次数
        int quantity = 1;
 
        public counterwrite(counter box, int request)
        {
            //构造函数
            counter = box;
            quantity = request;
        }
 
        //生产者向操作对象更新信息
        public void write()
        {
            for (int i = 1; i &lt;= quantity; i++)
                counter.write(i);
        }
    }
 
    /// <summary>
    /// 消费者
    /// </summary>
    public class counterread
    {
        counter counter;
        //生产者生产次数
        int quantity = 1;
 
        public counterread(counter box, int request)
        {
            //构造函数
            counter = box;
            quantity = request;
        }
 
        //消费者从操作对象中获取信息
        public void read()
        {
            for (int i = 1; i &lt;= quantity; i++)
                counter.read();
        }
    }
C#多线程的同步与通信

3、线程操作

C#多线程的同步与通信
       counter counter = new counter();
 
            counterread read = new counterread(counter, 10);
            counterwrite write = new counterwrite(counter, 10);
 
            thread th1 = new thread(new threadstart(read.read));
            thread th2 = new thread(new threadstart(write.write));
 
            th1.start();
            th2.start();
 
            th1.join();
            th2.join();
 
            console.readline();
C#多线程的同步与通信

通过lock锁定counter对象的引用,初始readflag为false控制线程1等待读取:monitor.wait(this),
线程2写入,然后更改readflag,然后执行:monitor.pulse(this),通知等待队列中的线程请求对象状态已发生改变,
线程1锁定this,执行读操作,然后更改readflag,线程1和线程2交互执行写读的操作。
同时因为readflag的存在和交替更新,避免了死锁情况的发生。