2013-01-07 13 views
8

Po czytałem this pytanie z an answer z wytłoków ....Blokowanie pola lub zmiennej lokalnej?

czasem widzę ludzi blokowania na zmiennej lokalnej .

Czy ten kod jest uszkodzony?

public void Do() 
{ 
object o = new Object(); 
lock (o) 
    { 
     ... 
    } 
} 

wierzę object o = new Object(); powinny być poza metoda jako Field.

Ponieważ każdy wątek otrzymuje nowe wystąpienie o, będzie wiele zamków.

Czego mi tu brakuje? Czy nie powinien on blokować pól w tym konkretnym przypadku?

Odpowiedz

8

wierzę obiekt O = nowy obiekt(); powinien znajdować się poza metodą jako pole.

Ponieważ każdy wątek otrzymuje nowe wystąpienie o, będzie wiele zamków.

Czy czegoś tu brakuje? bo wiem, że powinien zablokować pola (w tym konkretnym przypadku).

Twoje zrozumienie jest prawidłowe. Kod jest uszkodzony. W tej implementacji, mimo że blokada będzie aktywna, nie zapewni synchronizacji, ponieważ będzie na różnych obiektach.

Od MSDN-lock c#

Na ogół uniknąć blokowania na rodzaj publicznego, lub przypadki poza kontrolą kodzie za.Wspólne konstrukty lock (this), zamek (typeof (MyType)), a blokada ("myLock") naruszać niniejszych wytycznych:

  • lock (this) jest problem, jeśli instancja mogą być dostępne publicznie.
  • lock (typeof (MyType)) jest problemem, jeśli MyType jest publicznie dostępny.
  • blokada ("myLock") jest problemem, ponieważ każdy inny kod w procesie używający tego samego ciągu będzie mieć tę samą blokadę.

Najlepszą praktyką jest zdefiniowanie prywatnego obiektu do zablokowania lub prywatnej statycznej zmiennej obiektowej w celu ochrony danych wspólnych dla wszystkich instancji.

2

Tworzysz obiekt o za każdym razem, gdy wywoływana jest twoja metoda. Blokowanie nie zadziała. Mam na myśli, że inne wątki nie będą czekać, aż blokada nie zostanie zasygnalizowana i przejmie kontrolę nad zasobem kontrolowanym przez tę blokadę. Zwykle obiekty blokujące są prywatną zmienną w klasie, więc wszystkie metody spoglądają na ten sam obiekt.

2

ja osobiście nie widzę żadnego powodu użycia tego, jak lock prostu ustawia pole w specjalnej instancji z odo sygnalizowanego stanu. Inne wątki mogą sprawdzić stan tej instancji i na jej podstawie wykonać kod wewnątrz instrukcji lock lub czekać na jej wydanie.

Posiadanie zmiennej lokalnej za każdym razem przydzieli nową instancję, więc dla każdego wątku będzie w porządku.

Nie widzę w tym żadnego znaczenia.

5

Tak. To jest złamane.

Chcesz statycznego obiektu tylko do odczytu jako pole prywatne do zablokowania. Jak podejrzewasz, twój przykładowy kod tworzy nowy obiekt za każdym razem, gdy wywołujesz Do, a zatem blokada nie będzie miała nic do trzymania i nie zadziała w ogóle.

private static object syncRoot = new object(); 

lock (syncRoot) { } 
+0

to nie musi być statyczne. (chyba że celowanie w inną instancję) –

+0

czyniąc ją statyczną tylko do odczytu, nie szkodzi, tylko ją zabezpiecza (nawet jeśli nie jest wymagana). – Tilak

+2

Uzgodnione. To nie musi być statyczne. Zależy od tego, co chronisz. –

1

Blokowanie zmiennej lokalnej, praca lock won's. Blokowanie zmiennej globalnej może zostać zastosowane do synchronizacji wielu wątków.

using System; 
     using System.Collections.Generic; 
     using System.Linq; 
     using System.Text; 
     using System.Threading.Tasks; 
     using System.Threading; 

     namespace testLock 
     { 
      class Program 
      { 
       public static void Main() 
       { 
        // Start a thread that calls a parameterized static method. 
        for(int i = 0; i< 10;i++) 
        { 
         Thread newThread = new Thread(DoWork); 
         newThread.Start(i); 
        } 

        Console.ReadLine(); 
       } 

       static object gObject= new object(); 
       public static void DoWork(object data) 
       { 
        int len = (int)data % 3; 
        object tmp = new object(); 
        Console.WriteLine("to lock...... Data='{0}' sleepTime:{1}", data, len); 
        lock (tmp)//tmp won't work, change tmp to gObject to see different output, which is good locking case) 
        { 
         Console.WriteLine("in lock...... Data='{0}' sleepTime:{1}", data, len); 

         Thread.Sleep( len* 1000); 
         Console.WriteLine("Static thread procedure. Data='{0}' sleepTime:{1}", data, len); 
        } 
       } 

      } 
     } 

    **Lock temp variable,will output:** 
    to lock...... Data='1' sleepTime:1 
    in lock...... Data='1' sleepTime:1 
    to lock...... Data='2' sleepTime:2 
    in lock...... Data='2' sleepTime:2 
    to lock...... Data='0' sleepTime:0 
    in lock...... Data='0' sleepTime:0 
    Static thread procedure. Data='0' sleepTime:0 
    to lock...... Data='3' sleepTime:0 
    in lock...... Data='3' sleepTime:0 
    Static thread procedure. Data='3' sleepTime:0 
    to lock...... Data='4' sleepTime:1 
    in lock...... Data='4' sleepTime:1 
    to lock...... Data='5' sleepTime:2 
    in lock...... Data='5' sleepTime:2 
    to lock...... Data='6' sleepTime:0 
    in lock...... Data='6' sleepTime:0 
    Static thread procedure. Data='6' sleepTime:0 
    to lock...... Data='7' sleepTime:1 
    in lock...... Data='7' sleepTime:1 
    to lock...... Data='8' sleepTime:2 
    in lock...... Data='8' sleepTime:2 
    to lock...... Data='9' sleepTime:0 
    in lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='9' sleepTime:0 
    Static thread procedure. Data='1' sleepTime:1 
    Static thread procedure. Data='4' sleepTime:1 
    Static thread procedure. Data='7' sleepTime:1 
    Static thread procedure. Data='2' sleepTime:2 
    Static thread procedure. Data='5' sleepTime:2 
    Static thread procedure. Data='8' sleepTime:2 

    **Then lock gObject, will print:** 
    to lock...... Data='0' sleepTime:0 
    in lock...... Data='0' sleepTime:0 
    to lock...... Data='1' sleepTime:1 
    to lock...... Data='2' sleepTime:2 
    Static thread procedure. Data='0' sleepTime:0 
    in lock...... Data='1' sleepTime:1 
    to lock...... Data='3' sleepTime:0 
    to lock...... Data='4' sleepTime:1 
    to lock...... Data='5' sleepTime:2 
    to lock...... Data='6' sleepTime:0 
    to lock...... Data='7' sleepTime:1 
    to lock...... Data='8' sleepTime:2 
    to lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='1' sleepTime:1 
    in lock...... Data='5' sleepTime:2 
    Static thread procedure. Data='5' sleepTime:2 
    in lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='9' sleepTime:0 
    in lock...... Data='2' sleepTime:2 
    Static thread procedure. Data='2' sleepTime:2 
    in lock...... Data='8' sleepTime:2 
    Static thread procedure. Data='8' sleepTime:2 
    in lock...... Data='7' sleepTime:1 
    Static thread procedure. Data='7' sleepTime:1 
    in lock...... Data='4' sleepTime:1 
    Static thread procedure. Data='4' sleepTime:1 
    in lock...... Data='3' sleepTime:0 
    Static thread procedure. Data='3' sleepTime:0 
    in lock...... Data='6' sleepTime:0 
    Static thread procedure. Data='6' sleepTime:0 
+0

W C# nie ma zmiennych globalnych. – Enigmativity

+1

masz rację, zmienną globalną w tym przykładzie mam na myśli jest zmienna statyczna w programie klasy. – terwxqian

Powiązane problemy