【问题标题】:Using Monitor Class使用监视器类
【发布时间】:2010-03-24 05:35:17
【问题描述】:

我想问几个关于在 .Net 中使用 Monitor 类的问题。

要了解问题,请查看以下代码。

public class MyClass
{
    private List<int> _MyCollection = new List<int>();

    public void GetLock()
    {
        Monitor.Enter(_MyCollection);
    }

    public void ReleaseLock()
    {
        Monitor.Exit(_MyCollection);
    }

    public void UpdateCollection(/*anyparam*/)
    {
        //update collection without lock on collection
    }
}

public class MyAppMain
{
    private static MyClass myclass = new MyClass();

    public static void main(args)
    {
        try
        {
            myclass.GetLock();

            //an operation that does not do any update on myclass but wanted 
            //to ensure that the collection within myclass never update
            //while its doing following opetion

            //Do somthing
        }
        finally
        {
            myclass.ReleaseLock();
        }
    }
}

现在这是对监视器的正确使用吗?我是否需要使用 Pulse 或 PulseAll 来发出等待线程的信号?如果需要,应该在退出函数之前或之后使用 plus 吗?

问候 穆巴沙尔

【问题讨论】:

  • 除非您在一般线程方面的经验比在特定的 .NET 线程方面更有经验,否则我会认真重新考虑这样做,以便在不锁定的情况下更新集合。

标签: .net synchronization locking


【解决方案1】:

是的,您对 Monitor 的使用是正确的。

也就是说,您可以使用lock 语句使代码更简洁:

public static void main(args)
{
    lock(myclass)
    {
    }
}

【讨论】:

  • 实际上,如果您将 my List 替换为 List> 并获取锁和释放锁仅适用于主列表中的特定 List。那么 lock 语句将不适用。简而言之,我不想锁定整个集合对象,而是使用 GetLock 和 Release Lock 函数锁定该集合中的一部分。
  • @MubasharAhmad - lock 语句可以使用Monitor.Enter 可以使用的任何对象。因此,您可以向 MyClass public Object GetLockTarget() { return ...; } 添加一个函数,然后通过执行 lock(myclass.GetLockTarget()) 将其锁定
【解决方案2】:

获取锁然后在 finally 块中释放它是正确的。我会在 try 块开始之前获得锁,但它可能不会伤害任何东西,除非尝试获得锁时抛出异常。

对于您实际尝试做的事情,您将需要重新考虑您的目标是什么。根据是否关注性能,您可以查看ReaderWriterLock。如果争用较低,请考虑锁定每个操作,但使用自旋锁 - 这对于不倾向于重叠但可能重叠的操作非常便宜。

另外:我认为您需要重新考虑更新集合而不锁定的概念,除非您可以确保只有一个线程将更新集合。

【讨论】:

  • 1.您在尝试之前获得锁是正确的,我通常会按照您的建议进行操作。 2. 关于 ReaderWriterLockSlim 的使用,您再次正确,我正在考虑使用它,因为我添加了这篇文章;)。实际上,上面的代码并不完全是我想要做的,而只是对此的简要反映。 3.对不起,我的阅读能力不好,我无法理解你说的内容,然后是“Also:”
  • 3.简单的。我不知道你的线程经验水平如何。我认为,如果您没有 very 强大的线程背景,那么示例代码中的注释 //update collection without lock on collection 意味着您正走在一条非常危险的道路上,除非您的将使用您没有告诉我们的类。
  • 糟糕,实际上我忘了在 //do 之后添加 UpdateCollection 函数调用,因为调用者已经使用 GetLock 函数获取了锁。
  • 好吧,你还没有提到任何关于 Pulse/PluseAll 功能的信息,在使用 Monitor 时是否必须在 Exit 功能后调用??
  • 没有。 Pulse/PulseAll 必须在 Exit() 之前调用,并且仅在其他线程调用 Wait() 时才需要调用。
猜你喜欢
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 2015-10-31
  • 1970-01-01
相关资源
最近更新 更多