我正在开发一个程序,其中多个线程共享公共资源,因此在修改此公共资源时必须进行同步。
基本要求:
为此,我创建了一个带有两个Reader线程和两个Writer线程的示例程序,并在读取和编写公共资源时实现了lock
(例如string
)。
就像下面一样。
object lockObj;
private string commonString;
public string CommonResource
{
get
{
lock (lockObj)
{
//adding sleep to magnify error condition when reading takes longer time
Thread.Sleep(1000 * 2);
return commonString;
}
}
set
{
lock (lockObj)
{
Thread.Sleep(1000 * 5);
commonString = value;
}
}
}
它可以很好地限制两个同时读写或写入,但它也限制了两个同时读取普通数据(这是不需要的,并使读取不必要地慢)。
我可以通过添加布尔标志来实现这一点,这些标志可以跟踪读写过程并相应地更新它们的自我。如下所示
但我更倾向于首先使用内部机制(如果有的话)来实现这一目标,而不是按照自己的方式创建。
bool isReadingInProgress = false;
bool isWritingInProgress = false;
public string ReadData()
{
string val;
while (isWritingInProgress)
{
Thread.Sleep(10);
}
isReadingInProgress = true;
val = commonString;
Thread.Sleep(2 * 1000);
isReadingInProgress = false;
return val;
}
public void WriteData(string val)
{
while(isReadingInProgress || isWritingInProgress)
{
Thread.Sleep(10);
}
isWritingInProgress = true;
commonString = val;
Thread.Sleep(5 * 1000);
isWritingInProgress = false;
}
我对上面的代码感到不舒服,因为当它们两个实际上只是一个公共资源(比如我希望同步的字符串)时,对布尔标志的依赖性非常高。所以我必须使这些布尔线程安全(如果我错了,请纠正我)。
有没有更好的方法来做到这一点?
如果不是,我应该使用锁定(如我在第一个代码中所示)并且具有慢读取功能,或者我应该使用此布尔值而不必费心使它们的线程安全吗?
调用此线程如下所示
static void Main(string[] args)
{
commonResourceClass = new CommonResourceClass(); //class which holds data
Thread writerThread1 = new Thread(() => WriterThreadRunner("writer 1"));
Thread writerThread2 = new Thread(() => WriterThreadRunner("writer 2"));
Thread readerThread1 = new Thread(() => ReaderThreadRunner("reader 1"));
Thread readerThread2 = new Thread(() => ReaderThreadRunner("reader 2"));
writerThread1.Start();
readerThread1.Start();
writerThread2.Start();
readerThread2.Start();
}
static void WriterThreadRunner(string threadName)
{
while (true)
{
//commonResourceClass.CommonResource = "Written";
commonResourceClass.WriteData("Written");
}
}
static void ReaderThreadRunner(string threadName)
{
while (true)
{
//string Data = commonResourceClass.CommonResource;
string Data = commonResourceClass.ReadData();
}
}