2011-10-12 94 views
2

所以我知道你可以使用一个信号量和其他可能的方法来确定一个锁是否会成功和/或有多少个线程在等待锁,但是你可以在锁定自己?如何测试锁内等待线程

我的情况是我有一个事件处理程序,可以由List中的许多对象调用。我想在一个锁内做一个测试,看看在继续之前所有的对象是否处于正确的状态。对象过渡到适当的状态然后引发此事件,因此在单个线程模型中,当最后一个引发此事件时,所有对象都处于正确状态,我们继续。但是在我看来,使用多线程时,多个对象可能会转换到我正在检查的状态,但尚未处理此事件,因为它们正在等待锁定。因此,锁内的条件状态检查将是真实的,但是直到所有线程完成处理该事件为止都将继续执行。我只需要它是真实的,因为最后一个线程被处理,以确保我们不会太快。

例如,在半写实代码:

object _LockObj = new object(); 

void Event_Handler(object sender, EventArgs e) 
{ 
    MyObject originator = sender as MyObject; 
    if(originator == null) 
     return; 

    *Do stuff with the originator* 

    lock(_LockObj) 
    { 
     if(ListOfMyObjects.FindAll(o => o.State == DesiredState) 
          .Count == ListOfMyObjects.Count 
           && *nothing waiting at the lock*) 
     { 
      *Proceed* 
     } 
    } 
} 

我完全愿意接受我的做法是臭下手,并且我正在寻找解决的办法是没有实际意义,如果我在做正确首先,但我不确定如何以线程安全的方式正确执行此操作。

我打算给MyObject添加更多状态,并通过在*Do stuff with the originator*部分设置相应的状态来管理流程,但是从这里转换MyObject并不合适,更不用说我必须实现一个为每个引发异味变得不简单的事件状态持有状态!

因此,如果有做“没有设定锁定等待”检查那么这就是我想去除非我失去了一个非常简单的实现模式,有助于在这种情况下的方式的简单方法。

+1

您正在寻求一个线程比赛错误作为功能。在你断定没有线程正在等待之后的一个纳秒内,一个线程可以进入该方法。 –

回答

3

首先,不幸的是,测试其他等待lock()语句的线程不会得到你想要的结果。例如,如果对象A,B和C已经转换到所需的状态并且已经提升了事件,那么可能仅对一个对象调用Event_Handler,在那一点上称为A。稍后,相同的处理程序将在某个时刻为B和C运行。所以你所有的对象现在应该处于期望的状态,并且没有线程在锁上等待,但是你有可能。不想“继续”。即使你这样做,你也需要考虑,同样的事情可能会在B之后立即发生,然后再为C发生,所以“继续”可能会运行三次...

这是一个简单的建议,但您可以使用反击测试有多少对象实际上引发了事件。如果柜台没有提供足够的信息,您也可以使用其他清单。重要的一点是,无论您使用哪种方法,只需在同一个_LockObj的锁内更新计数器/列表/其他机制。然后可能在继续运行后重置该计数器。如果您需要访问其他地方的计数器,请确保您使用相同的lock(_LockObj),这将确保您在其他关键部分内不会更改计数器。

object _LockObj = new object(); 
int _counter = 0; 

void Event_Handler(object sender, EventArgs e) 
{ 
    MyObject originator = sender as MyObject; 
    if(originator == null) 
     return; 

    *Do stuff with the originator* 

    lock(_LockObj) 
    { 
     ++_counter; 
     if (_counter == ListOfMyObjects.Count) 
     { 
      *Proceed* 

      _counter = 0; 
     } 
    } 
} 

编辑:去除对象的状态冗余校验。

+0

这次复查没用吗?如果这两个部分不符合,你将永远无法进入。 – xanatos

+0

谢谢@xanatos,已经更新了代码。代码的其他部分可能会更新对象的状态,我们仍然需要检查它,但是如果是这样的话,我们应该(A)在这里看到更多的代码,并且(b)还应该假设_counter改变了它的值其他部分也是。 – Jonno

+0

啊我有多愚蠢,不考虑事件在检查后进入方法的场景:(所以无论我的解决方案是什么,我需要独立跟踪完成,然后只有在我的独立测试成功后才进行。 – Akuma

1

你有没有想过一个简单的同步工作项目队列?所以当事件发生时,它只是将处理排队,并且处理按顺序由单独的线程完成?

+0

不知道这是如何帮助,除非你能详细说明,因为我需要推迟进行,直到它是适当的,问题是我现在该如何进行。我现在要根据Jonno的回应来实现一些东西(因为截止日期尚未结束),除非有更简单的事情发生。 – Akuma

+0

在一个单线程模型中,你说它工作正常,大概你有一个机制来解决事件是最后被触发的时间。如果您在工作项目中使用相同的逻辑,以确定它是否应该执行处理,则可以像处理单个线程一样对待它。实际上,您将多个线程引发的事件汇集到一个同步队列中,以便您可以将它视为单个线程。我承认我可能冲过那个答案,所以我猜你确实希望处理位是异步的,但其余的不是? – blaaaaaaah