Perché l'oggetto blocco deve essere statico?


112

È molto comune utilizzare un oggetto di sola lettura statico privato per il blocco nel multi threading. Capisco che privato riduce i punti di ingresso all'oggetto di blocco stringendo l'incapsulamento e quindi l'accesso al più essenziale.

Ma perché statico?

private static readonly object Locker = new object();

Alla fine il campo viene utilizzato solo all'interno della mia classe, e potrei anche usare solo questo:

private readonly object Locker = new object();

Eventuali commenti?

AGGIORNARE:

Come esempio ho incollato questo codice (solo un esempio). Potrei usare un armadietto statico o non statico su questo ed entrambi funzionerebbero bene. Considerando la risposta di seguito, dovrei piuttosto definire il mio armadietto in questo modo? (Scusa, ho un colloquio la prossima settimana e ho bisogno di conoscere ogni dettaglio :)

private readonly object Locker = new object();

Ed ecco il codice:

    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();
        }

Grazie


15
Per quanto ne so, statico viene solitamente utilizzato per renderlo indipendente dall'istanza. Se esistono più istanze di "MyWorkerClass", solo una alla volta può essere eseguita con i dati forniti (supponendo che utilizzino tutte risorse condivise).
Brad Christie

2
La modifica manca di un dettaglio importante: dove sono _servicee si _waithandletrovano? esempio? statico? altro? Ciò potrebbe , ad esempio, sincronizzare deliberatamente l'accesso a un server remoto ...
Marc Gravell

giusto, con la seconda modifica: sì, da questa fine delle cose potresti bloccare per istanza. Ci possono sono stati motivi per renderlo statico, anche se - se il dev originale voleva (come detto) per l'accesso sincronizzare in modo che il server riceve solo una richiesta alla volta da questo AppDomain ... non posso so se questo è il caso o se è stato solo accidentale.
Marc Gravell

Risposte:


177

Non è "molto comune utilizzare un oggetto di sola lettura statico privato per il blocco in multi threading" - piuttosto, è comune utilizzare un blocco con la granularità appropriata / scelta . A volte lo è static. Più spesso, IMO, non lo è, ma è un'istanza basato .

Il momento principale in cui vedi un staticblocco è per una cache globale o per il caricamento differito di dati / singleton globali. E in quest'ultimo caso, ci sono modi migliori per farlo comunque .

Quindi dipende davvero: come viene Lockerutilizzato nel tuo scenario? Protegge qualcosa che è di per statico? In tal caso, il blocco dovrebbe essere statico. Se sta proteggendo qualcosa che è basato sull'istanza , allora IMO il blocco dovrebbe anche essere basato sull'istanza.


24
Potreste fornire maggiori dettagli su un modo migliore per il caricamento differito dei dati globali?
bizi

Uso sempre uno statico / volatile perché se ci sono diversi posti in cui è basato sull'istanza, vorrei comunque controllare il mio metodo / variabile a cui si accede in modo thread-safe. Molte istanze possono accedere alle stesse risorse e desidero controllarlo. Anch'io vorrei vedere il meglio nel farlo. Hai un'ottima reputazione e sono sicuro che la tua risposta sarà altrettanto ottima per me da adottare. Per favore rispondi?
Andrew Simpson

82

Esso non deve essere statico, infatti a volte si deve non essere statico.

La variabile dovrebbe risiedere nello stesso ambito dei metodi in cui viene utilizzata per il blocco. Se i metodi sono statici, la variabile dovrebbe essere statica e se i metodi sono metodi di istanza, la variabile dovrebbe essere una variabile di istanza.

Una variabile statica continuerà a funzionare quando viene utilizzata per bloccare un metodo di istanza, ma in tal caso verrà bloccato troppo. Bloccherai tutti i metodi in tutte le istanze, non solo i metodi nella stessa istanza.


28
+1 per "a-ha" ... Bloccherai tutti i metodi in tutte le istanze, non solo i metodi nella stessa istanza.
Radarbob

3
@radarbob - Dettaglio minore: non bloccherai tutti i metodi , prendi solo un lucchetto a cui potrebbero interessare più client. I metodi non vengono mai bloccati, è solo che è stato preso il mutex.
Erno

Sospetto che la formulazione di questa risposta possa essere fuorviante - il blocco non dovrebbe avere a che fare con l'ambito dei metodi - dovrebbe riguardare solo l'ambito dei dati condivisi a cui si accede con quei metodi. Il metodo dell'istanza potrebbe non accedere a dati condivisi (e quindi non è necessario il blocco), potrebbe accedere a dati condivisi statici (e quindi richiedere un blocco statico, anche il refactoring potrebbe essere una buona idea), lo stesso per static ...
Alexei Levenkov

@AlexeiLevenkov: Hai ragione sul fatto che l'ambito dovrebbe effettivamente essere deciso dal fatto che i dati siano statici o meno, ma anche l'ambito dei metodi dovrebbe essere deciso da questo, quindi tutto combacia. I dati dell'istanza normalmente non richiedono il blocco, ma se l'istanza è condivisa tra i thread, sarà necessario il blocco.
Guffa

28

L'ambito e la durata di un lucchetto possono / devono dipendere dalla "cosa" che si desidera bloccare. I blocchi statici vengono utilizzati principalmente per bloccare cose statiche.


3
Dettaglio minore: il lucchetto non è statico, l'oggetto che utilizzi per identificare il lucchetto è statico. Un altro piccolo dettaglio: non blocchi le "cose".
Guffa

2
Sì, penso che se provassimo a bloccare le "cose" sbagliate, potrebbero essere troppo grandi e forti, e un giorno scappare.
ProfK

12
@Guffa È strano, in un commento sopra hai giustamente detto: "Stai solo complicando le cose", ora vedo 1 minuto prima di dirlo, sembra che stavi complicando le cose :)
Nicholas Petersen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.