2012-07-19 197 views
1

我碰到一块的C#代码来了今天这个样子:线程安全

lock(obj) 
{ 
    // perform various operations 
    ... 

    // send a message via a queue but in the same process, Post(yourData, callback) 
    messagingBus.Post(data,() => 
    { 
    // perform operation 
    ... 
    if(condition == true) 
    { 
     // perform a long running, out of process operation 
     operation.Perform(); 
    } 
    } 
} 

我的问题是这样的:可以在回调函数以这样的方式永远被调用,以使锁定(OBJ )到不是在operation.Perform()被调用之前被释放?也就是说,是否有一种方法可以在持有锁的同一个线程上调用回调函数,并且在该线程释放了锁之前?

编辑:messagingBus.Post(...)可以被认为是插入队列,然后立即返回。回调在其他线程上调用,可能来自线程池。

对于operation.Perform(),您可以将其读为Thread.Sleep(10000) - 只是运行很长时间并且不会共享或变更任何状态的东西。

+0

如果lambda表达式或Post是异步的,那么完全可以在锁释放后调用Perform。 – vcsjones 2012-07-19 20:05:18

+0

@SamIam:固定! – endian 2012-07-19 20:06:33

+0

@vcsjones:谢谢,是的,我的问题恰恰相反 - 在Perform()运行时锁可以保持吗? – endian 2012-07-19 20:07:30

回答

0

我在猜测。

Post in .net通常意味着该作品将由另一个线程完成或在其他时间完成。

所以是的,这不仅可能在obj上的锁定将在Perform被调用之前被释放,它很有可能会发生。但是,这并不能保证。执行可能会在释放锁之前完成。

这并不意味着它是一个问题。 “执行各种操作”部分可能需要锁定。 messagingBus可能需要锁才能对动作进行排队。里面的工作根本不需要锁,在这种情况下代码是线程安全的。

这完全是一种猜测,因为没有关于正在做什么工作的概念,为什么它必须在锁内,以及什么是Post或执行什么操作。所以代码可能是完全安全的,或者它可能是可怕的缺陷。

0

不知道messagingBus.Post在做什么,你不能说。 如果 Post调用它所给出的委托(在你的例子中是lambda表达式),那么当这个lambda执行时,锁将会到位。 如果稍后委托执行的过帐时间表,则在执行lambda时锁将不会。目前还不清楚锁(obj)是什么,锁定对messagingBus.Post的调用,或者是什么...详细说明messagingBus变量的类型(包括完整名称空间)对于提供更好的细节将有很长的路要走。

+0

@endian能否提供更多信息? – 2012-07-23 20:21:06

0

如果回调异步执行,那么是的,当Perform()除非Post()做了某些特定的事情以避免这种情况(这是不寻常的)时,锁仍然可以被保持。

如果回调调度与调用Post()的同一线程上(例如,在线程池只有一个线程的极端示例中),典型的线程池实现将不会执行回调,直到线程完成这是当前的任务,在这种情况下,它会要求它在执行Perform()之前释放锁。

0

如果不知道messagingBus.Post是如何实现的,就不可能回答你的问题。异步API通常不能保证回调将真正并发执行。例如,.Net APM方法(如FileStream.BeginRead)可能会决定同步执行操作,在这种情况下,回调将在调用BeginRead的同一线程上执行。在这种情况下,返回的IAsyncResult.CompletedSynchronously将被设置为true。