線程安全對象 - 靜態與否?

[英]Thread safety object - static or not?


I was recently in an interview and the tech guy asked me about how to make an application thread-safe.

我最近在接受采訪時,技術人員問我如何使應用程序線程安全。

Well, after explaining the lock() correctly, he said it is not a good idea to have the object as static.

好吧,在正確解釋了lock()之后,他說將對象設置為靜態並不是一個好主意。

private static readonly object _syncLock = new object();

He claimed the reason is that static makes that object slower for threads to lock than if it was non static. Is this true?

他聲稱原因是靜態使得線程鎖定的對象比非靜態時更慢。這是真的?

EDIT: Nonetheless I am still not sure. What is the difference between these three approaches?

編輯:盡管如此,我仍然不確定。這三種方法有什么區別?

private static readonly object _syncLock = new object();
public static readonly object _syncLock = new object();
private readonly object _syncLock = new object();

6 个解决方案

#1


If a lock object should be static or not depends on the object you want to lock. If you want to lock an instance of a class you cannot use a static lock object. If you want to lock static data you cannot use an instance lock object. So there seems not to be any choice.

如果鎖定對象應該是靜態的,則取決於要鎖定的對象。如果要鎖定類的實例,則不能使用靜態鎖定對象。如果要鎖定靜態數據,則無法使用實例鎖定對象。所以似乎沒有任何選擇。

You could think about using a static or an instance lock object to lock the access to instance data, but this results in different behaviors. With an instance lock object you lock only an instance while an static lock object will lock all instances. So no choice for performance tuning here, too.

您可以考慮使用靜態或實例鎖定對象來鎖定對實例數據的訪問,但這會導致不同的行為。使用實例鎖定對象時,只鎖定實例,而靜態鎖定對象將鎖定所有實例。所以在這里也沒有選擇性能調優的選擇。

#2


He claimed the reason is that static is run at runtime instead of compilation and would make that object slower for threads to lock than if it was non static.

他聲稱原因是靜態是在運行時運行而不是編譯,並且會使線程鎖定的對象比非靜態時更慢。

This doesn't really make any sense - I think either the interviewer did not know what he was talking about, or maybe you misunderstood his point.

這沒有任何意義 - 我認為面試官不知道他在說什么,或者你誤解了他的觀點。

#3


Sometimes in job interviews I say something I know is incorrect or something that is utter nonsense to see if the candidate will effectively argue his point or just give up and agree.

有時在求職面試中,我會說一些我知道的不正確的事情,或者說這個候選人是否會有效地論證他的觀點或者只是放棄並同意這些事情完全是胡說八道。

Oh and here's an excellent article by Jeffrey Richter on the proper uses of lock. :)

哦,這是傑弗里里希特關於正確使用鎖的一篇優秀文章。 :)

#4


Use a non static object for the lock whenever you need to make sure the same instance isn't manipulated by different threads at the same time.

每當需要確保同一實例不被同一個不同的線程操縱時,請使用非靜態對象進行鎖定。

Lets say you have some List classes, with a special Reorder method that accepts some strange arguments. Consider if you need to reorder 100 different lists during some paralel processes. You only care that different threads don't manipulate the same list at the same time, as it might affect your reorder logic. You don't need a static lock, as you don't care when different lists are being manipulated at the same time.

假設你有一些List類,有一個特殊的Reorder方法,它接受一些奇怪的參數。考慮是否需要在一些並行處理過程中重新排序100個不同的列表。您只關心不同的線程不會同時操作同一個列表,因為它可能會影響您的重新排序邏輯。您不需要靜態鎖定,因為您在同時操作不同列表時並不在意。

A simple example of a scenario with a static lock, is initialization of some static data, where you want to make sure the load logic is ran only once. Like some Cache or a Singleton.

具有靜態鎖定的方案的一個簡單示例是初始化某些靜態數據,您希望確保加載邏輯僅運行一次。像一些Cache或Singleton。

#5


If you have only one instance of a class that shares between multiple threads, it's ok to use normal object. but if you have multiple objects of a class that share between multiple threads, you have to use static object.

如果只有一個類的實例在多個線程之間共享,則可以使用普通對象。但是如果您有多個在多個線程之間共享的類的對象,則必須使用靜態對象。

On the other hand, with normal object you can manage concurrency for one instance of a class and with static object you can manage concurrency in the scope of all instances of a class.

另一方面,使用普通對象,您可以管理類的一個實例的並發性,使用靜態對象,您可以在類的所有實例的范圍內管理並發性。

#6


The others are correct that the choice of using a static of instance field depends on what state (class-level or instance-level) that you need to lock, and there is no relevant difference in speed for the lock itself. BUT if you really only need to use instance data then your app could run much faster using lock(this) rather than locking out all threads from accessing the data of ANY instance. That might have been what the interviewer was getting at - in an application where multiple threads are only using instance data it should indeed run faster if you only lock the instance because it won't block other threads from using other instances.

其他正確的選擇使用靜態實例字段取決於您需要鎖定的狀態(類級別或實例級別),並且鎖定本身的速度沒有相關差異。但是如果你真的只需要使用實例數據那么你的app可以使用lock(this)運行得更快,而不是鎖定所有線程訪問任何實例的數據。這可能是面試官得到的 - 在一個多線程只使用實例數據的應用程序中,如果你只鎖定實例,它確實應該運行得更快,因為它不會阻止其他線程使用其他實例。

Conversely if threads are accessing class-level (static) state then you need to lock them all with a single object. When I need to do this, a pattern I've used is to lock the type of the class like this:

相反,如果線程正在訪問類級(靜態)狀態,那么您需要使用單個對象將它們全部鎖定。當我需要這樣做時,我使用的模式是鎖定類的類型,如下所示:

[Edit - not such a good idea after all, see comments below]

[編輯 - 畢竟不是一個好主意,請參閱下面的評論]

lock(typeof(MyClass))
{
  // use class-level data
}

This avoids the necessity of creating the static object field.

這避免了創建靜態對象字段的必要性。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/04/22/7254dab250b8f4fb3d92ea0153366fbc.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com