Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程锁和监视器类不工作_C#_Multithreading_Class_Locking_Monitor - Fatal编程技术网

C# 多线程锁和监视器类不工作

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

我有一个可以读写的文件。我需要确保当它被写入时,没有其他人会尝试写入它

我对整个函数设置了一个锁,它允许读或写,但仍然会出现错误,例如 进程无法访问文件“FILENAME”,因为其他进程正在使用该文件

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点,您的锁将如预期的那样成功

特别提示:我并不是在陈述一种生活方式