【问题标题】:Why is this program in error? `Object synchronization method was called from an unsynchronized block of code`为什么这个程序出错了? `从未同步的代码块中调用了对象同步方法`
【发布时间】:2010-12-26 01:53:43
【问题描述】:

这段代码有什么问题?我得到一个“对象同步方法是从不同步的代码块中调用的”。我在谷歌上发现了一个结果,说我可能在锁定之前释放了一个互斥锁,但根据我的输出,情况并非如此。这是互斥代码,中间没有其他代码。

-edit- 抱歉各位,贴错了。

我的输出

1W
1W
2W

代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace sqliteTest
{
    class Program
    {
        static volatile Mutex mut1 = new Mutex();
        static volatile Mutex mut2 = new Mutex();
        static void Main(string[] args)
        {
            mut1.WaitOne(); Console.WriteLine("1W");
            Thread oThread = new Thread(new ThreadStart(fn2));
            oThread.Start();
            mut1.WaitOne(); Console.WriteLine("1W");
            update(0);
        }
        static void fn2()
        {
            mut2.WaitOne(); Console.WriteLine("2W");
            mut1.ReleaseMutex(); Console.WriteLine("1R");
            mut2.WaitOne(); Console.WriteLine("2W");
            update(1);
            mut1.ReleaseMutex(); Console.WriteLine("1R");
        }
        static void update(int t)
        {
            mut2.ReleaseMutex(); Console.WriteLine("2R");
            if (t == 0)
            {
                mut1.WaitOne();
                Console.WriteLine("1W");
            }
        }
    }
}

【问题讨论】:

  • 第 37 行或第 49 行。这两个线程都在我的调试器中。
  • 哎呀。 +1 dtb。在新粘贴的代码中,它发生在 23 和 30

标签: c# .net synchronization mutex


【解决方案1】:

您的代码似乎有很多问题。主线程启动一个新线程,然后调用更新。在更新中,它尝试解锁 mutex2,但尚未锁定 mutex2,因此失败并出现异常。

即使修复了这个错误,其他线程也同样注定失败。它会在锁定 mutex1 之前尝试释放它。

你想在这里做什么?您是否将 Mutex 与 AutoResetEvent 混淆了?

另外我猜这两行是复制/粘贴错误,因为它们出现了两次:

        mut2.WaitOne(); Console.WriteLine("2W");
        mut1.ReleaseMutex(); Console.WriteLine("1R");

【讨论】:

  • 抱歉,我在粘贴时不小心跳过了部分代码。现在可能更有意义了。
  • 我还是不明白。现在您的主线程连续两次锁定 mutex1,然后解锁它不拥有的 mutex2。这样做的目的是什么?你到底想做什么?
【解决方案2】:

这不是一个很好的错误消息,Windows 会产生它。它的真正含义是您在您不拥有的互斥锁上调用 ReleaseMutex。您将通过

克服第一个异常
static volatile Mutex mut2 = new Mutex(true);

但是当它在 mut1 上调用 ReleaseMutex 时,它会在线程内死掉,而它并不拥有它。不确定您要做什么,代码对我来说没有多大意义。

【讨论】:

  • 抱歉,我在粘贴时不小心跳过了部分代码。现在可能更有意义了。
  • 嗯,还是一样的问题。运行 fn2() 的线程不拥有 mut1 互斥锁,它不能释放它不拥有的互斥锁。使用 ManualResetEvent 向其他线程发出信号。
  • 好的。那就是问题所在。事实证明,我认为互斥锁不是递归的。我想要信号量。使用信号量(1,1);并将 .ReleaseMutex 更改为 Release 代码完全按预期运行。
  • @HansPassant - 您非常乐于助人,感谢您的贡献!
【解决方案3】:

是的,其他人是对的: 这段代码没有任何意义。

但是由于这个页面在谷歌中的排名很高(虽然它没有帮助)我将所有搜索者重定向到这个关于线程同步的伟大网站:

http://www.albahari.com/threading/part2.aspx

埃尔穆

【讨论】:

    【解决方案4】:

    只是想发布另一个我遇到的奇怪场景,因为它可能对其他人有所帮助。在 Visual Studio 2010 C# express 中打开一个项目时,我遇到了这个异常。现在我的项目确实包含一些线程,但我不希望它在加载代码时使 Visual Studio 崩溃,这正是正在发生的事情。

    关于我的代码的注释:我正在使用在 STA 线程 ([STAThreadAttribute]) 上调用的 MethodInvoker 和 BeginInvoke(在检查是否 InvokeRequired 之后)。同样,这段代码甚至没有机会运行。 Visual Studio Express 会在加载项目时崩溃。此外,这一切都是在我得到一个奇怪的 FileNotFoundException 之后开始发生的,当它声称找不到参考时,它同样使 VS 崩溃。我通过最终从代码中完全删除引用及其所有用法来解决这个问题,构建,关闭 VS,再次打开它并打开解决方案,然后才开始遇到这个神秘的错误。此项目中没有互斥锁或监视器,也没有与先前删除的引用相关联(仅绘制一些图形的自定义库)。

    经过大量研究(谷歌搜索),我发现了大量与 VS 崩溃无关的有趣信息,我最终决定尝试在 Visual Studio 2010 Professional 中打开解决方案,看看它是否会崩溃好吧。它没有。我对代码和项目设置进行了一些令牌更改,构建并保存了所有内容,将其关闭,现在我可以在 Visual Studio Express 中再次打开解决方案而不会出现任何错误!很奇怪。不知道这是否会对任何人有所帮助,因为这似乎有点在这个例外的可能性边缘。我怀疑我的所有东西的注册表都存在问题,因为我过去遇到过一些奇怪的情况,Visual Studio 和我的注册表无法相处,所有这些都会影响我的项目加载方式,甚至迫使我恢复我的注册表,运行注册表清理程序,然后重新启动以恢复正常行为。

    【讨论】:

    • 哇。发布5年后被选为答案!我想知道 OP 是否重新审视了这个问题,或者遇到了现代的问题,这是否为他们解决了这个问题?
    猜你喜欢
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 2012-09-14
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多