一个写入线程,三个读取线程,写入和读取不能同时进行,可以并行读取,读取完毕后才能进行下一论和写入,代码如下:static ReaderWriterLock rwLock = new ReaderWriterLock();
static object locker = new object();
static void Main(string[] args)
{
    Thread t = null;
    for(int i = 0; i < 1; i++)
    {
        t = new Thread(Writer);
        t.Name = i.ToString();
        t.Start();
    }    for(int i = 0; i<3; i++)
    {
        t = new Thread(Reader);
        t.Name = i.ToString();
        t.Start();
    }    Console.ReadLine();
}static void Writer()
{
    while(true)
    {
        try
        {
            rwLock.AcquireWriterLock(3000);
            Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
            try
            {
                Thread.Sleep(10000);
            }
            finally
            {
                rwLock.ReleaseWriterLock();
                Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is exit");
            }
        }
        catch(ApplicationException)
        {
            Console.WriteLine("writer:" + Thread.CurrentThread.Name + " wait time out");
        }
    }
}static void Reader()
{
    while (true)
    {
        rwLock.AcquireReaderLock(-1);
        Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
        try
        {
            Thread.Sleep(5000);
        }
        finally
        {
            Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is exit");
            rwLock.ReleaseReaderLock();
        }
    }
}但ReaderWriterLock有这么一个特性:
当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。这就意味着这个要求:读取完毕后才能进行下一论和写入不能被保证,而个人觉得不用ReaderWriterLock实现一个写入三个读取这样的功能代码是很繁琐的,所以才有了ReaderWriterLock这么个东西,但ReaderWriterLock却又没有一种机制来保证读取结束后才进行下一轮写入这样的特性,鸡肋,高手说明一下,会者举一个能够更好说明ReaderWriterLock使用时机的范例代码,3Q

解决方案 »

  1.   

    需要读取资源的数据,而不是修改资源的数据,在这种情况下获取资源的独占权会影响运行效率,
    使用ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,
    那么可以获得多个读的访问权,单个写入的独占权,
    如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待
        private static ReaderWriterLock m_readerWriterLock = new ReaderWriterLock();
            private static void Read()
            {
                while (true)
                {
                    Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireReaderLock");
                    m_readerWriterLock.AcquireReaderLock(10000);
                    Console.WriteLine(String.Format("ThreadName : {0} m_int : {1}", Thread.CurrentThread.Name, m_int));
                    m_readerWriterLock.ReleaseReaderLock();
                }
            }
            private static void Writer()
            {
                while (true)
                {
                    Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireWriterLock");
                    m_readerWriterLock.AcquireWriterLock(1000);
                    Interlocked.Increment(ref m_int);
                    Thread.Sleep(5000);
                    m_readerWriterLock.ReleaseWriterLock();
                    Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " ReleaseWriterLock");
                }
            }         private void button2_Click(object sender, EventArgs e)
             {
                 Thread readThread = new Thread(new ThreadStart(Read));
                 readThread.Name = "ReadThread1";
                 Thread readThread2 = new Thread(new ThreadStart(Read));
                 readThread2.Name = "ReadThread2";
                 Thread writeThread = new Thread(new ThreadStart(Writer));
                 writeThread.Name = "WriterThread";
                 readThread.Start();
                 readThread2.Start();
                 writeThread.Start();
                 readThread.Join();
                 readThread2.Join();
                 writeThread.Join();
                 Console.ReadLine();
             }
      

  2.   

    我还是看不出楼上的代码有什么特色之处怎么说明了ReaderWriterLock的实际用途,实际用途!
      

  3.   

    在接下来的这个例子中,4个线程被启动:一个不停地往列表中增加项目;另一个不停地从列表中移除项目;其它两个不停地报告列表中项目的个数。前两者获得写的锁,后两者获得读的锁。每个锁的超时参数为10秒。//异常处理一般要使用来捕捉ApplicationException,这个例子中出于方便而省略了
        class Program
        {
            static ReaderWriterLock rw = new ReaderWriterLock();
            static List<int> items = new List<int>();
            static Random rand = new Random();
            static void Main(string[] args)
            {
                new Thread(delegate() { while (true) AppendItem(); }).Start();
                new Thread(delegate() { while (true) RemoveItem(); }).Start();
                new Thread(delegate() { while (true) WriteTotal(); }).Start();
                new Thread(delegate() { while (true) WriteTotal(); }).Start();
            }
            static int GetRandNum(int max)
            {
                lock (rand) return rand.Next(max);
            }
            static void WriteTotal()
            {  
                //获取读锁
                rw.AcquireReaderLock(10000);
                int tot = 0;
                foreach (int i in items)
                    tot += i;
                Console.WriteLine(tot);
                //释放读锁
                rw.ReleaseReaderLock();
            }
            static void AppendItem()
            {
                //获取写锁
                rw.AcquireWriterLock(10000);
                items.Add(GetRandNum(1000));
                Thread.SpinWait(400);
                //释放写锁
                rw.ReleaseWriterLock();
            }
            static void RemoveItem()
            { //获取写锁
                rw.AcquireWriterLock(10000);
                if (items.Count > 0)
                    items.RemoveAt(GetRandNum(items.Count));
                //释放写锁
                rw.ReleaseWriterLock();
            }
        }往List中加项目要比移除快一些,这个例子在AppendItem中包含了SpinWait来保持项目总数平衡。