问题描述
有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
①允许多个读者可以同时对文件执行读操作;
②只允许一个写者往文件中写信息;
③任一写者在完成写操作之前不允许其他读者或写者工作;
④写者执行写操作前,应让已有的读者和写者全部退出。
读者优先算法
在此算法中,读进程是优先的,简单来讲,当存在读者进程时,写者操作将被延迟,并且只要有一个读者进程活跃,随后而来的读者进程都将被允许访问文件。这样的方式下,会导致写者进程可能长时间等待,且存在写者进程“饿死”的情况。
using System;
using System.Threading;
/*读者优先*/
namespace ConsoleApp1
{
class Program
{
private static Semaphore RWMutex; // 读写互斥信号量
private static Semaphore CountMutex; //读者计数互斥信号量
private static int Rcount = 0; // 正在进行读操作的读者数目
static void Main(string[] args)
{
RWMutex = new Semaphore(1, 1);
CountMutex = new Semaphore(1, 1);
Thread Writer = new Thread(writer);
Thread Reader0 = new Thread(reader);
Thread Reader1 = new Thread(reader);
Thread Reader2 = new Thread(reader);
Writer.Start();
Reader0.Start();
Reader1.Start();
Reader2.Start();
}
//写者进程
protected static void writer()
{
while (true)
{
RWMutex.WaitOne(); // 判断是否可以写
Console.WriteLine("write");
Thread.Sleep(1000);
RWMutex.Release(); // 写完成,释放资源
}
}
//读者进程
protected static void reader()
{
while (true)
{
CountMutex.WaitOne(); // 互斥访问count变量
Rcount++;
if (Rcount == 1) // 第一个读进程占用写进程的资源
{
RWMutex.WaitOne();
}
CountMutex.Release();
Console.WriteLine("read-" + Rcount);
Thread.Sleep(1000);
CountMutex.WaitOne();
Rcount--;
if (Rcount == 0) // 最后一个读进程释放写进程的资源
{
RWMutex.Release();
}
CountMutex.Release();
}
}
}
}
写者优先算法
如果希望写进程优先,即当有读进程正在读共享文件时,有写进程请求访问,这时应禁止后续读进程的请求,等待到已在共享文件的读进程执行完毕则立即让写进程执行,只有在无写进程执行的情况下才允许读进程再次运行。
using System;
using System.Threading;
//写者优先
namespace ConsoleApp1
{
class Class1
{
private static Semaphore RCMutex, WCMutex; // 读者、写者计数互斥
private static Semaphore rsem, wsem; // 读写互斥
private static int Rcount = 0, Wcount = 0; // 读者、写者计数
static void Main(string[] args)
{
RCMutex = new Semaphore(1, 1);
WCMutex = new Semaphore(1, 1);
rsem = new Semaphore(1, 1);
wsem = new Semaphore(1, 1);
Thread Writer = new Thread(writer);
Thread Reader = new Thread(reader);
Reader.Start();
Writer.Start();
}
//writer
protected static void writer()
{
while (true)
{
WCMutex.WaitOne();
Wcount++;
if (Wcount == 1)
{
rsem.WaitOne();
}
Thread.Sleep(1000);
WCMutex.Release();
wsem.WaitOne();
Console.WriteLine("write-" + Wcount);
wsem.Release();
WCMutex.WaitOne();
Wcount--;
if (Wcount == 0)
{
rsem.Release();
}
WCMutex.Release();
}
}
//reader
protected static void reader()
{
while (true)
{
rsem.WaitOne();
RCMutex.WaitOne();
Rcount++;
if (Rcount == 1)
{
wsem.WaitOne();
}
Thread.Sleep(1000);
RCMutex.Release();
rsem.Release();
Console.WriteLine("read-" + Rcount);
RCMutex.WaitOne();
Rcount--;
if (Rcount == 0)
{
wsem.Release();
}
RCMutex.Release();
}
}
}
}
公平竞争算法
using System;
using System.Threading;
namespace ConsoleApp1
{
class Class2
{
//
private static Semaphore RCMutex, WCMutex, RMutex, WMutex;
private static int Rcount = 0;
static void Main(string[] args)
{
RCMutex = new Semaphore(1, 1);
WCMutex = new Semaphore(1, 1);
RMutex = new Semaphore(1, 1);
WMutex = new Semaphore(1, 1);
Thread Writer0 = new Thread(writer);
Thread Reader0 = new Thread(reader);
Reader0.Start();
Writer0.Start();
}
public static void reader()
{
while (true)
{
Console.WriteLine("reader waiting");
RMutex.WaitOne();
RCMutex.WaitOne();
Rcount++;
if (Rcount == 1)
{
WMutex.WaitOne();
}
RCMutex.Release();
Console.WriteLine("read-" + Rcount);
Thread.Sleep(1000);
RCMutex.WaitOne();
Rcount--;
if (Rcount == 0)
{
WMutex.Release();
}
RCMutex.Release();
RMutex.Release();
}
}
public static void writer()
{
while(true)
{
Console.WriteLine("Writer waiting");
RMutex.WaitOne();
WMutex.WaitOne();
Console.WriteLine("write");
Thread.Sleep(1000);
WMutex.Release();
RMutex.Release();
}
}
}
}