問題描述
有讀者和寫者兩組併發進程,共享一個文件,當兩個或以上的讀進程同時訪問共享數據時不會產生副作用,但若某個寫進程和其他進程(讀進程或寫進程)同時訪問共享數據時則可能導致數據不一致的錯誤。因此要求:
①允許多個讀者可以同時對文件執行讀操作;
②只允許一個寫者往文件中寫信息;
③任一寫者在完成寫操作之前不允許其他讀者或寫者工作;
④寫者執行寫操作前,應讓已有的讀者和寫者全部退出。
讀者優先算法
在此算法中,讀進程是優先的,簡單來講,當存在讀者進程時,寫者操作將被延遲,並且只要有一個讀者進程活躍,隨後而來的讀者進程都將被允許訪問文件。這樣的方式下,會導致寫者進程可能長時間等待,且存在寫者進程“餓死”的情況。
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();
}
}
}
}