您的位置:首页 > 博客中心 > 编程语言 >

C#读写者线程(用AutoResetEvent实现同步)

时间:2022-03-21 06:15

转载自 http://blog.csdn.net/livelylittlefish/article/details/2735440

 

本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

 

using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace TestAutoResetEvent { /// /// 读写者线程 /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出 /// class Program { //写线程将数据写入myData static int myData = 100; //读写次数 const int readWriteCount = 10; //false:初始时没有信号 static AutoResetEvent autoResetEvent = new AutoResetEvent(false); static void Main(string[] args) { //开启一个读线程(子线程) Thread readerThread = new Thread(new ThreadStart(ReadThreadProc)); readerThread.Name = "ReaderThread"; readerThread.Start(); for (int i = 1; i <= readWriteCount; i++) { Console.WriteLine("MainThread writing : {0}", i); //主(写)线程将数据写入 myData = i; //主(写)线程发信号,说明值已写过了 //即通知正在等待的线程有事件发生 autoResetEvent.Set(); Thread.Sleep(0); } //终止线程 readerThread.Abort(); } static void ReadThreadProc() { while (true) { //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号) autoResetEvent.WaitOne(); Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData); } } } }


运行结果如下:

 

 

gxlsystem.com,布布扣

 

由运行结果可以看出,写线程写入的数据有丢失,主要原因是写线程没有给读线程留足够的时间去进行读操作。

 

3. 对1进行修改

将主线程睡眠时间改为非0值,观察运行结果。

[Csharp] view plaincopyprint?
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text; 
  4.  
  5. using System.Threading; 
  6.  
  7. namespace TestAutoResetEvent 
  8.     /// <summary> 
  9.     /// 读写者线程 
  10.     /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出 
  11.     /// </summary> 
  12.     class Program 
  13.     { 
  14.         //写线程将数据写入myData 
  15.         staticint myData = 100; 
  16.  
  17.         //读写次数 
  18.         constint readWriteCount = 10; 
  19.  
  20.         //false:初始时没有信号 
  21.         static AutoResetEvent autoResetEvent = new AutoResetEvent(false); 
  22.  
  23.         staticvoid Main(string[] args) 
  24.         { 
  25.             //开启一个读线程(子线程) 
  26.             Thread readerThread = new Thread(new ThreadStart(ReadThreadProc)); 
  27.             readerThread.Name = "ReaderThread"; 
  28.             readerThread.Start(); 
  29.  
  30.             for (int i = 1; i <= readWriteCount; i++) 
  31.             { 
  32.                 Console.WriteLine("MainThread writing : {0}", i); 
  33.  
  34.                 //主(写)线程将数据写入 
  35.                 myData = i; 
  36.  
  37.                 //主(写)线程发信号,说明值已写过了 
  38.                 //即通知正在等待的线程有事件发生 
  39.                 autoResetEvent.Set(); 
  40.  
  41.                 Thread.Sleep(1); 
  42.             } 
  43.  
  44.             //终止线程 
  45.             readerThread.Abort(); 
  46.         } 
  47.  
  48.         staticvoid ReadThreadProc() 
  49.         { 
  50.             while (true) 
  51.             { 
  52.                 //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号) 
  53.                 autoResetEvent.WaitOne(); 
  54.                 Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData); 
  55.             } 
  56.         } 
  57.     } 
using System;
using System.Collections.Generic;
using System.Text;

using System.Threading;

namespace TestAutoResetEvent
{
    /// 
    /// 读写者线程
    /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出
    /// 
    class Program
    {
        //写线程将数据写入myData
        static int myData = 100;

        //读写次数
        const int readWriteCount = 10;

        //false:初始时没有信号
        static AutoResetEvent autoResetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            //开启一个读线程(子线程)
            Thread readerThread = new Thread(new ThreadStart(ReadThreadProc));
            readerThread.Name = "ReaderThread";
            readerThread.Start();

            for (int i = 1; i <= readWriteCount; i++)
            {
                Console.WriteLine("MainThread writing : {0}", i);

                //主(写)线程将数据写入
                myData = i;

                //主(写)线程发信号,说明值已写过了
                //即通知正在等待的线程有事件发生
                autoResetEvent.Set();

                Thread.Sleep(1);
            }

            //终止线程
            readerThread.Abort();
        }

        static void ReadThreadProc()
        {
            while (true)
            {
                //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号)
                autoResetEvent.WaitOne();
                Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData);
            }
        }
    }
}

运行结果如下:

 

gxlsystem.com,布布扣

 

有结果可知,当主线程睡眠时间大于0值时,读线程即有足够的时间读取写线程写入的数据。这个睡眠时间的长短可以根据实际应用中子线程的计算量设定。

 

4. 对1再进行修改

主线程在写完数据后根本不睡吗呢?这个时候会发生什么事情?

[Csharp] view plaincopyprint?
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text; 
  4.  
  5. using System.Threading; 
  6.  
  7. namespace TestAutoResetEvent 
  8.     /// <summary> 
  9.     /// 读写者线程 
  10.     /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出 
  11.     /// </summary> 
  12.     class Program 
  13.     { 
  14.         //写线程将数据写入myData 
  15.         staticint myData = 100; 
  16.  
  17.         //读写次数 
  18.         constint readWriteCount = 10; 
  19.  
  20.         //false:初始时没有信号 
  21.         static AutoResetEvent autoResetEvent = new AutoResetEvent(false); 
  22.  
  23.         staticvoid Main(string[] args) 
  24.         { 
  25.             //开启一个读线程(子线程) 
  26.             Thread readerThread = new Thread(new ThreadStart(ReadThreadProc)); 
  27.             readerThread.Name = "ReaderThread"; 
  28.             readerThread.Start(); 
  29.  
  30.             for (int i = 1; i <= readWriteCount; i++) 
  31.             { 
  32.                 Console.WriteLine("MainThread writing : {0}", i); 
  33.  
  34.                 //主(写)线程将数据写入 
  35.                 myData = i; 
  36.  
  37.                 //主(写)线程发信号,说明值已写过了 
  38.                 //即通知正在等待的线程有事件发生 
  39.                 autoResetEvent.Set(); 
  40.  
  41.                 //Thread.Sleep(1); 
  42.             } 
  43.  
  44.             //终止线程 
  45.             readerThread.Abort(); 
  46.         } 
  47.  
  48.         staticvoid ReadThreadProc() 
  49.         { 
  50.             while (true) 
  51.             { 
  52.                 //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号) 
  53.                 autoResetEvent.WaitOne(); 
  54.                 Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData); 
  55.             } 
  56.         } 
  57.     } 
  58. }<pre></pre> 
using System;
using System.Collections.Generic;
using System.Text;

using System.Threading;

namespace TestAutoResetEvent
{
    ///
    /// 读写者线程
    /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出
    ///
    class Program
    {
        //写线程将数据写入myData
        static int myData = 100;

        //读写次数
        const int readWriteCount = 10;

        //false:初始时没有信号
        static AutoResetEvent autoResetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            //开启一个读线程(子线程)
            Thread readerThread = new Thread(new ThreadStart(ReadThreadProc));
            readerThread.Name = "ReaderThread";
            readerThread.Start();

            for (int i = 1; i <= readWriteCount; i++)
            {
                Console.WriteLine("MainThread writing : {0}", i);

                //主(写)线程将数据写入
                myData = i;

                //主(写)线程发信号,说明值已写过了
                //即通知正在等待的线程有事件发生
                autoResetEvent.Set();

                //Thread.Sleep(1);
            }

            //终止线程
            readerThread.Abort();
        }

        static void ReadThreadProc()
        {
            while (true)
            {
                //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号)
                autoResetEvent.WaitOne();
                Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData);
            }
        }
    }
}

 

运行结果如下:

 

gxlsystem.com,布布扣

 

有结果可知,不睡眠的情况和睡眠时间为0(即Thread.Sleep(0);)效果产不多,只是不睡眠丢失的数据更多了。

 

5. 对1再修改

将传递给AutoResetEvent的构造函数的参数设置为true,观察运行结果。

 

[Csharp] view plaincopyprint?
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text; 
  4.  
  5. using System.Threading; 
  6.  
  7. namespace TestAutoResetEvent 
  8.     /// <summary> 
  9.     /// 读写者线程 
  10.     /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出 
  11.     /// </summary> 
  12.     class Program 
  13.     { 
  14.         //写线程将数据写入myData 
  15.         staticint myData = 100; 
  16.  
  17.         //读写次数 
  18.         constint readWriteCount = 10; 
  19.  
  20.         //false:初始时没有信号 
  21.         static AutoResetEvent autoResetEvent = new AutoResetEvent(true); 
  22.  
  23.         staticvoid Main(string[] args) 
  24.         { 
  25.             //开启一个读线程(子线程) 
  26.             Thread readerThread = new Thread(new ThreadStart(ReadThreadProc)); 
  27.             readerThread.Name = "ReaderThread"; 
  28.             readerThread.Start(); 
  29.  
  30.             for (int i = 1; i <= readWriteCount; i++) 
  31.             { 
  32.                 Console.WriteLine("MainThread writing : {0}", i); 
  33.  
  34.                 //主(写)线程将数据写入 
  35.                 myData = i; 
  36.  
  37.                 //主(写)线程发信号,说明值已写过了 
  38.                 //即通知正在等待的线程有事件发生 
  39.                 autoResetEvent.Set(); 
  40.  
  41.                 Thread.Sleep(0); 
  42.             } 
  43.  
  44.             //终止线程 
  45.             readerThread.Abort(); 
  46.         } 
  47.  
  48.         staticvoid ReadThreadProc() 
  49.         { 
  50.             while (true) 
  51.             { 
  52.                 //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号) 
  53.                 autoResetEvent.WaitOne(); 
  54.                 Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData); 
  55.             } 
  56.         } 
  57.     } 
  58. }<pre></pre> 
using System;
using System.Collections.Generic;
using System.Text;

using System.Threading;

namespace TestAutoResetEvent
{
    ///
    /// 读写者线程
    /// 主线程写,子线程读,且只有将数据写入后,读线程才能将其读出
    ///
    class Program
    {
        //写线程将数据写入myData
        static int myData = 100;

        //读写次数
        const int readWriteCount = 10;

        //false:初始时没有信号
        static AutoResetEvent autoResetEvent = new AutoResetEvent(true);

        static void Main(string[] args)
        {
            //开启一个读线程(子线程)
            Thread readerThread = new Thread(new ThreadStart(ReadThreadProc));
            readerThread.Name = "ReaderThread";
            readerThread.Start();

            for (int i = 1; i <= readWriteCount; i++)
            {
                Console.WriteLine("MainThread writing : {0}", i);

                //主(写)线程将数据写入
                myData = i;

                //主(写)线程发信号,说明值已写过了
                //即通知正在等待的线程有事件发生
                autoResetEvent.Set();

                Thread.Sleep(0);
            }

            //终止线程
            readerThread.Abort();
        }

        static void ReadThreadProc()
        {
            while (true)
            {
                //在数据被写入前,读线程等待(实际上是等待写线程发出数据写完的信号)
                autoResetEvent.WaitOne();
                Console.WriteLine("{0} reading : {1}", Thread.CurrentThread.Name, myData);
            }
        }
    }
}

 

运行结果如下:

 

至此,我想我们应该明白AutoResetEvent构造函数的参数的意义了。 false:无信号,子线程的WaitOne方法不会被自动调用; true:有信号,子线程的WaitOne方法会被自动调用。

C#读写者线程(用AutoResetEvent实现同步),布布扣,bubuko.com

本类排行

今日推荐

热门手游