C# 多线程锁和监视器类不工作
我有一个可以读写的文件。我需要确保当它被写入时,没有其他人会尝试写入它 我对整个函数设置了一个锁,它允许读或写,但仍然会出现错误,例如 进程无法访问文件“FILENAME”,因为其他进程正在使用该文件C# 多线程锁和监视器类不工作,c#,multithreading,class,locking,monitor,C#,Multithreading,Class,Locking,Monitor,我有一个可以读写的文件。我需要确保当它被写入时,没有其他人会尝试写入它 我对整个函数设置了一个锁,它允许读或写,但仍然会出现错误,例如 进程无法访问文件“FILENAME”,因为其他进程正在使用该文件 public static TYPE Property{ get{ data mydata; Object obj = new object(); Monitor.Enter(obj); // check if data has not changed
public static TYPE Property{
get{
data mydata;
Object obj = new object();
Monitor.Enter(obj);
// check if data has not changed
// if it has not, just read
using (Stream stream = File.Open(fileLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
//....
}
// else, if data changed, then need to write to file to save the new data
using (Stream stream = File.Open(fileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) {
BinaryFormatter bf = new BinaryFormatter();
try {
bf.Serialize(stream, (data);
}
//DONE processing
Monitor.Pulse(obj);
Monitor.Exit(obj);
return data
}
您正在创建一个新的监视器,以便在每次调用该属性时锁定它。您需要锁定同一个监视器,否则锁定根本没有意义
你也应该使用一个“lock”语句——你从不等待,所以没有必要去脉动。目前,如果抛出任何异常,您将最终导致锁“泄漏”。这通常是一个非常糟糕的问题,但由于您没有重用锁,这就掩盖了问题
例如:
private static readonly object monitor = new object();
public static TYPE Property
{
get
{
lock(monitor)
{
// check if data has not changed
// if it has not, just read
using (Stream stream = File.Open(fileLocation,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
....
}
// else, if data changed, then need to write to
// file to save the new data
using (Stream stream = File.Open
(fileLocation, FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.Read))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, data);
}
return data;
}
}
}
顺便说一句,这看起来比我预期的要多。您确定某个方法没有意义吗?您正在创建一个新的监视器,以便在每次调用该属性时锁定它。您需要锁定同一个监视器,否则锁定根本没有意义
你也应该使用一个“lock”语句——你从不等待,所以没有必要去脉动。目前,如果抛出任何异常,您将最终导致锁“泄漏”。这通常是一个非常糟糕的问题,但由于您没有重用锁,这就掩盖了问题
例如:
private static readonly object monitor = new object();
public static TYPE Property
{
get
{
lock(monitor)
{
// check if data has not changed
// if it has not, just read
using (Stream stream = File.Open(fileLocation,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
....
}
// else, if data changed, then need to write to
// file to save the new data
using (Stream stream = File.Open
(fileLocation, FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.Read))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, data);
}
return data;
}
}
}
顺便说一句,这看起来比我预期的要多。你确定某个方法没有意义吗?好吧,监视。输入阻止试图在同一对象上设置锁的任何线程的访问。每次输入getter时,都会创建一个新对象,因此每个调用方都会得到一个互不了解的新锁 换句话说,没有锁定
作为旁注-为什么不使用lock语句?您仍然需要一个全局锁对象。好吧,监视。输入将阻止试图在同一对象上放置锁的任何线程的访问。每次输入getter时,都会创建一个新对象,因此每个调用方都会得到一个互不了解的新锁 换句话说,没有锁定
作为旁注-为什么不使用lock语句?您仍然需要一个全局锁对象。全局变量相对于局部变量的原因是锁实际上锁定了memeory中的一个引用点。每次实例化一个新对象时,即“object obj=new object();”,您都在创建一个新对象,在内存中有它自己的唯一指针。所以,当LOCK查看内存中的点是否被锁定时,它不是。因为它是内存中一个全新的引用点,唯一使用它的是进入您的属性的调用方。通过全局声明Obj变量,它将始终是内存中的同一点,并且lock可以实际验证,实际上,内存中的该点当前已锁定,或者它可以自行锁定 示例:(粗糙,但我认为它抓住了重点)
objectobj=newobject()代码>
现在你的记忆中有一个点看起来有点像:
记忆-
* obj1
现在,再次输入属性并再次创建新对象。您的系统内存现在看起来有点像
记忆-
* obj1
* obj2
在第一次行程中,您的锁正在检查内存中的“Obj1”。由于第一次访问您的酒店的调用方是唯一使用该Obj实例的调用方,因此它是唯一会锁定或检查其锁定的调用方。因为它正在内存中查看Obj引用的副本
在第二次行程中,您的锁在内存中选中“Obj2”
当您使用全局变量时,内存中的该点将持续存在,因此lock将始终检查内存中的同一点。它从不移动,而且在内存中始终是相同的引用点。因此,属性的所有调用者将始终使用内存中相同的referenece点,您的锁将如预期的那样成功
特别注意:我不是在说“obj”的寿命。我只是简单地说明这在多线程进程中是如何运行的。希望能有所帮助。全局变量与局部变量的区别在于,锁实际上锁定了memeory中的一个引用点,据我所知。每次实例化一个新对象时,即“object obj=new object();”,您都在创建一个新对象,在内存中有它自己的唯一指针。所以,当LOCK查看内存中的点是否被锁定时,它不是。因为它是内存中一个全新的引用点,唯一使用它的是进入您的属性的调用方。通过全局声明Obj变量,它将始终是内存中的同一点,并且lock可以实际验证,实际上,内存中的该点当前已锁定,或者它可以自行锁定
示例:(粗糙,但我认为它抓住了重点)
objectobj=newobject()代码>
现在你的记忆中有一个点看起来有点像:
记忆-
* obj1
现在,再次输入属性并再次创建新对象。您的系统内存现在看起来有点像
记忆-
* obj1
* obj2
在第一次行程中,您的锁正在检查内存中的“Obj1”。由于第一次访问您的酒店的调用方是唯一使用该Obj实例的调用方,因此它是唯一会锁定或检查其锁定的调用方。因为它正在内存中查看Obj引用的副本
在第二次行程中,您的锁在内存中选中“Obj2”
当您使用全局变量时,内存中的该点将持续存在,因此lock将始终检查内存中的同一点。它从不移动,而且在内存中始终是相同的引用点。因此,属性的所有调用者将始终使用内存中相同的referenece点,您的锁将如预期的那样成功
特别提示:我并不是在陈述一种生活方式