Mengapa objek kunci harus statis?

112

Sangat umum menggunakan objek hanya baca statis privat untuk mengunci multi threading. Saya memahami bahwa privat mengurangi titik masuk ke objek penguncian dengan memperketat enkapsulasi dan karena itu akses ke yang paling penting.

Tapi kenapa statis?

private static readonly object Locker = new object();

Pada akhirnya, bidang ini hanya digunakan di dalam kelas saya saja, dan saya juga bisa menggunakan ini sebagai gantinya:

private readonly object Locker = new object();

Ada komentar?

MEMPERBARUI:

Sebagai contoh saya telah menempelkan kode ini (hanya contoh). Saya bisa menggunakan loker statis atau non-statis untuk ini dan keduanya akan berfungsi dengan baik. Mempertimbangkan jawaban di bawah ini, saya harus mendefinisikan loker saya seperti ini? (Maaf saya ada wawancara minggu depan dan perlu tahu setiap detail :)

private readonly object Locker = new object();

Dan inilah kodenya:

    private int _priceA;
    private int _priceB;
    private EventWaitHandle[] _waithandle;
    private readonly IService _service;

//ctor
public ModuleAViewModel(IService service)
    {
        _service = service;
        _modelA = new ModelA();
        _waithandle = new ManualResetEvent[2];
        _waithandle[0] = new ManualResetEvent(false);
        _waithandle[1] = new ManualResetEvent(false);
        LoadDataByThread();
    }


 private void LoadDataByThread()
        {
            new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceA = _service.GetPriceA();
                                   }
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceB = _service.GetPriceB();
                                   }
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                               PriceA = _priceA;
                               PriceB = _priceB;
                           }).Start();
        }

Terima kasih

Houman
sumber
15
Sepengetahuan saya, statis biasanya digunakan untuk menjadikannya instance-agnostik. Jika beberapa contoh "MyWorkerClass" ada, hanya satu yang dapat berjalan dengan data yang diberikan pada satu waktu (dengan asumsi semuanya menggunakan sumber daya bersama).
Brad Christie
2
Hasil edit tidak memiliki detail penting: di mana _servicedan _waithandleberada? contoh? statis? lain? Itu bisa , misalnya, dengan sengaja menyinkronkan akses ke server jarak jauh ...
Marc Gravell
benar, dengan suntingan kedua: ya, dari ujung ini Anda bisa mengunci per contoh. Ada mungkin telah alasan untuk membuatnya statis, meskipun - jika dev asli ingin (seperti yang disebutkan) untuk mengakses sinkronisasi sehingga server hanya mendapat satu permintaan sekaligus dari AppDomain ini ... aku tidak bisa tahu apakah itu terjadi , atau apakah itu hanya kebetulan.
Marc Gravell

Jawaban:

177

Tidaklah "sangat umum untuk menggunakan objek hanya baca statis privat untuk mengunci multi threading" - sebaliknya, menggunakan kunci pada perincian yang sesuai / dipilih adalah hal yang umum . Terkadang memang begitu static. Lebih sering, IMO, bukan - tetapi berbasis instance .

Waktu utama Anda melihat statickunci adalah untuk cache global, atau untuk pemuatan data global / singletons yang ditangguhkan. Dan di kedua, ada cara yang lebih baik untuk melakukannya pula .

Jadi itu sangat tergantung: bagaimana Lockerdigunakan dalam skenario Anda? Apakah itu melindungi sesuatu yang dengan sendirinya statis? Jika demikian, kuncinya harus statis. Jika itu melindungi sesuatu yang berbasis instance , maka IMO kunci juga harus berbasis instance.

Marc Gravell
sumber
24
Bisakah Anda memberikan lebih banyak detail tentang cara yang lebih baik untuk menunda pemuatan data global?
bizi
Saya selalu menggunakan statis / volatile karena jika ada beberapa tempat yang berbasis instance, saya masih ingin mengontrol metode / variabel saya diakses dengan cara yang aman. Banyak contoh mungkin mengakses sumber yang sama dan saya ingin mengontrolnya. saya juga ingin melihat yang lebih baik dari melakukan ini. Anda memiliki reputasi yang baik dan saya yakin balasan Anda akan sama bagusnya untuk saya adopsi. Tolong balas?
Andrew Simpson
82

Tidak harus statis, bahkan terkadang tidak boleh statis.

Variabel harus berada dalam lingkup yang sama dengan metode yang Anda gunakan untuk mengunci. Jika metodenya statis, variabel harus statis, dan jika metodenya adalah metode instan, variabel tersebut harus berupa variabel instan.

Variabel statis akan tetap berfungsi saat digunakan untuk mengunci metode instance, tetapi Anda akan terlalu banyak mengunci. Anda akan mengunci semua metode dalam semua contoh, bukan hanya metode dalam contoh yang sama.

Guffa
sumber
28
1 untuk "a-ha" ... Anda akan mengunci semua metode dalam semua contoh, bukan hanya metode dalam contoh yang sama.
radarbob
3
@radarbob - Detail kecil: Anda tidak akan mengunci semua metode yang Anda cukup kunci sehingga lebih banyak klien tertarik. Metode tidak pernah dikunci, hanya saja mutex telah diambil.
Erno
Saya menduga pengungkapan jawaban ini bisa menyesatkan - penguncian tidak harus melakukan apa pun dengan cakupan metode - seharusnya hanya terkait dengan cakupan data bersama yang diakses dalam metode tersebut. Metode instans mungkin tidak mengakses data bersama apa pun (dan karenanya tidak perlu mengunci), dapat mengakses data bersama statis (dan karenanya memerlukan kunci statis, juga pemfaktoran ulang mungkin merupakan ide yang baik), sama untuk statis ...
Alexei Levenkov
@AlexeiLevenkov: Anda benar bahwa cakupan seharusnya diputuskan oleh apakah datanya statis atau tidak, tetapi ruang lingkup metode juga harus diputuskan olehnya, sehingga semuanya cocok satu sama lain. Data instance biasanya tidak perlu dikunci, tetapi jika instance dibagikan di antara utas, Anda perlu penguncian.
Guffa
28

Cakupan dan masa pakai kunci dapat / harus bergantung pada 'benda' yang ingin Anda kunci. Kunci statis sebagian besar digunakan untuk mengunci benda statis.

Erno
sumber
3
Detail kecil: Kunci tidak statis, objek yang Anda gunakan untuk mengidentifikasi kunci bersifat statis. Detail kecil lainnya: Anda tidak mengunci "barang".
Guffa
2
Ya, saya pikir jika kita mencoba mengunci "barang" yang salah, mereka mungkin terlalu besar dan kuat, dan suatu hari akan lolos.
ProfK
12
@ Guffa Aneh, dalam komentar di atas Anda dengan tepat mengatakan: "Kamu hanya hal-hal yang terlalu rumit," sekarang saya melihat 1 menit sebelum mengatakan itu, sepertinya Anda terlalu rumit :)
Nicholas Petersen