私は読み書き同期クラスを書いていますが、次に何をすべきかアドバイスが欲しいです。何らかの理由でRead
、 の途中で が発生するWrite
ことがありますが、その理由がわかりません。
これは私がこのクラスに望むものです:
- 書き込みと同時に読み取りを行うことはできません。
- 複数の読み取りが同時に発生する可能性があります。
- 一度に実行できる書き込みは 1 つだけです。
- 書き込みが必要な場合、既に実行中のすべての読み取りが続行され、新しい読み取りは許可されず、すべての読み取りが終了すると書き込みが実行されます。
.Net フレームワークにはこれを行うためのクラスがあることは知っていますが、私が知りたいのは、そのようなことを理解し、再現することです。私は車輪を再発明しているわけではありません。私は自分の車輪を作ることによってそれを理解しようとしています...たまたま私の車輪が少し四角いです。
私が現在持っているのはこれです:
public class ReadWriteSync
{
private ManualResetEvent read = new ManualResetEvent(true);
private volatile int readingBlocks = 0;
private AutoResetEvent write = new AutoResetEvent(true);
private object locker = new object();
public IDisposable ReadLock()
{
lock (this.locker)
{
this.write.Reset();
Interlocked.Increment(ref this.readingBlocks);
this.read.WaitOne();
}
return new Disposer(() =>
{
if (Interlocked.Decrement(ref this.readingBlocks) == 0)
this.write.Set();
});
}
public IDisposable WriteLock()
{
lock (this.locker)
{
this.read.Reset();
this.write.WaitOne();
}
return new Disposer(() =>
{
this.read.Set();
if (this.readingBlocks == 0)
this.write.Set();
});
}
class Disposer : IDisposable
{
Action disposer;
public Disposer(Action disposer) { this.disposer = disposer; }
public void Dispose() { this.disposer(); }
}
}
これは私のテストプログラムです...何か問題が発生すると、行が赤で表示されます。
class Program
{
static ReadWriteSync sync = new ReadWriteSync();
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.Gray;
Console.Clear();
Task readTask1 = new Task(() => DoReads("A", 20));
Task readTask2 = new Task(() => DoReads("B", 30));
Task readTask3 = new Task(() => DoReads("C", 40));
Task readTask4 = new Task(() => DoReads("D", 50));
Task writeTask1 = new Task(() => DoWrites("E", 500));
Task writeTask2 = new Task(() => DoWrites("F", 200));
readTask1.Start();
readTask2.Start();
readTask3.Start();
readTask4.Start();
writeTask1.Start();
writeTask2.Start();
Task.WaitAll(
readTask1, readTask2, readTask3, readTask4,
writeTask1, writeTask2);
}
static volatile bool reading;
static volatile bool writing;
static void DoWrites(string name, int interval)
{
for (int i = 1; i < int.MaxValue; i += 2)
{
using (sync.WriteLock())
{
Console.ForegroundColor = (writing || reading) ? ConsoleColor.Red : ConsoleColor.Gray;
writing = true;
Console.WriteLine("WRITE {1}-{0} BEGIN", i, name);
Thread.Sleep(interval);
Console.WriteLine("WRITE {1}-{0} END", i, name);
writing = false;
}
Thread.Sleep(interval);
}
}
static void DoReads(string name, int interval)
{
for (int i = 0; i < int.MaxValue; i += 2)
{
using (sync.ReadLock())
{
Console.ForegroundColor = (writing) ? ConsoleColor.Red : ConsoleColor.Gray;
reading = true;
Console.WriteLine("READ {1}-{0} BEGIN", i, name);
Thread.Sleep(interval * 3);
Console.WriteLine("READ {1}-{0} END", i, name);
reading = false;
}
Thread.Sleep(interval);
}
}
}
このすべての何が問題なのですか...正しく行う方法について何かアドバイスはありますか?