簡體   English   中英

C#lambdas中的線程安全

[英]Thread safety in C# lambdas

我今天遇到了一段這樣的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();
    }
  }
}

我的問題是這樣的:回調函數是否曾經以一種導致在調用operation.Perform()之前釋放lock(obj)的方式被調用? 即,有沒有一種方法可以在持有該鎖的同一線程上並且在該線程釋放該鎖之前調用該回調函數?

編輯:messagingBus.Post(...)可以假定為插入到隊列中,然后立即返回。 該回調是在其他一些線程上調用的,可能是從線程池中調用的。

對於operation.Perform(),您可以將其讀取為Thread.Sleep(10000)-只是可以長時間運行並且不會共享或改變任何狀態的東西。

我猜。

.net中的Post通常意味着工作將由另一個線程或在另一個時間完成。

因此,是的,不僅可能在調用Perform之前釋放對obj的鎖定,而且很有可能會發生。 但是,不能保證。 Perform可能會在釋放鎖定之前完成。

這並不意味着有問題。 “執行各種操作”部分可能需要鎖定。 essagingBus可能需要鎖才能將操作排隊。 內部的工作可能根本不需要鎖,在這種情況下,代碼是線程安全的。

這全是猜測,因為沒有概念來說明正在執行什么工作,為什么必須將其放在鎖中以及Post或執行的工作。 因此,該代碼可能是完全安全的,或者可能存在嚴重的缺陷。

不知道messagementBus.Post在做什么,就無法分辨。 如果 Post調用了委托(在您的示例中為lambda表達式),則在執行該lambda時將鎖定該鎖。 如果 Post安排該委托在以后執行,則在執行lambda時,鎖不會處於適當位置。 目前尚不清楚lock(obj)的用途是什么,用於鎖定對messages.Bus.Post的調用,還是什么...詳細說明messages.Bus變量的類型(包括完整的名稱空間)將大大有助於提供更好的細節。

如果回調是異步執行的,則可以,當Perform()時,該鎖可能仍會保持,除非Post()做一些特定的操作來避免這種情況(這是不尋常的)。

如果回調與調用Post()安排在同一線程上(例如,在極端示例中,線程池只有1個線程),那么典型的線程池實現將在線程完成其當前任務之前不執行回調,在這種情況下,這將要求它在執行Perform()之前釋放鎖。

如果不知道messagingBus.Post是如何實現的,就不可能回答您的問題。 異步API通常不保證回調將真正並發執行。 例如,.Net APM方法(例如FileStream.BeginRead)可能決定同步執行該操作,在這種情況下,回調將在稱為BeginRead的同一線程上執行。 在這種情況下,返回的IAsyncResult.CompletedSynchronously將設置為true。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM