C#模拟读者写者问题

2019-04-14 21:23发布

原本是操作系统的一个上机作业,上课没注意听所以一直都不知道,明天都要交了只好用C#简单写了个,好在.NET强大的FCL提供了读者写者锁类,因此实现起来方便许多,读者写者锁在读者数目多于写者时会显示出比监视器(类似于操作系统中讲到的管程)更好的性能。具体的说,每个读者线程在访问临界资源的时候申请读者锁,访问结束后释放锁,同样,写者线程在访问资源时申请写者锁,访问结束释放锁。如果锁被一个写者线程而不是读者线程所拥有的话,AcquireReaderLock会被阻塞,锁被任何一个线程拥有,AcquireWriterLock都会被阻塞。这样也就实现了多个线程可并发读取临界资源但任意时刻只能有一个线程执行写操作,并且如果有线程在读,写线程将无法进入。按照上述,便基本解决了读者-写者问题,但是很明显这种解决方案是读线程优先的。 以下是具体的代码实现,模拟两个写者和四个读者,有不妥的地方希望及时指正哈   using System;
using System.Threading;

namespace Reader_Writer
{
    
class Reader_Writer
    {
        
static Random rnd = new Random(unchecked((int)DateTime.Now.Ticks));
        
//缓冲区模拟有100页的书
        static byte[]  buffer = new byte[100];
        
static ReaderWriterLock rwlock = new ReaderWriterLock();
        
static Thread[] writers = new Thread[2];
        
static Thread[] readers = new Thread[4];

        
static void Main(string[] args)
        {
            
string[] writerNames = {"W1""W2"};
            
string[] readerNames = {"R1""R2""R3""R4"};
            
//初始化书本内容
            for (int i=0; i<100; i++)
            {
                buffer[i] 
= (byte)(i+1);
            }
            
//初始化2个写者线程
            for (int i=0; i<2; i++)
            {
                writers[i] 
= new Thread(new ThreadStart(WriteMethod));
                writers[i].Name 
= writerNames[i];
            }
            
//初始化4个读者线程
            for (int i=0; i<4; i++)
            {
                readers[i] 
= new Thread(new ThreadStart(ReadMethod));
                readers[i].Name 
= readerNames[i];
            }

            
//指定线程开始执行的顺序,可调整
            readers[0].Start();
            writers[
0].Start();
            readers[
1].Start();
            writers[
1].Start();
            readers[
2].Start();
            readers[
3].Start();
        }

        
static void ReadMethod()
        {
            
//申请读者锁,在此期间允许其他读者但阻止任何写者
            rwlock.AcquireReaderLock(Timeout.Infinite);
            
try
            {
                
int page = rnd.Next(1101);
                Console.WriteLine(
"读者线程 {0} 正在读第 {1} 页...", Thread.CurrentThread.Name, page);
                
//模拟读过程
                Thread.Sleep(rnd.Next(30006000));
                Console.WriteLine(
"读者线程 {0} 完成读操作.", Thread.CurrentThread.Name);
            }
            
catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            
finally
            {
                
//释放读者锁
                rwlock.ReleaseReaderLock();
            }
        }

        
static void WriteMethod()
        {
            
//申请写者锁,在此期间阻止任何读者和写者
            rwlock.AcquireWriterLock(Timeout.Infinite);
            
try
            {
                Console.WriteLine(
" 写者线程 {0} 开始工作...", Thread.CurrentThread.Name);
                
int page = rnd.Next(1101);
                Console.WriteLine(
"写者线程 {0} 正在改写第 {1} 页的内容", Thread.CurrentThread.Name, page);
                Thread.Sleep(rnd.Next(
30006000));                 Console.WriteLine("写者线程 {0} 完成工作... ", Thread.CurrentThread.Name);
            }
            
catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            
finally
            {
                
//释放写者锁
                rwlock.ReleaseWriterLock();
            }
        }
    }
}