Laden...

Schlüsselwort lock - Verständnisfrage

Erstellt von mosspower vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.149 Views
mosspower Themenstarter:in
456 Beiträge seit 2007
vor 15 Jahren
Schlüsselwort lock - Verständnisfrage

Hallo "Kollegen",

Erst mal folgender Beispielcode ...


public class App {

    static IList<String> lockList = new List<String>() { "Maus", "Monitor", "Notebook" };

    public static void Main() {
      new Thread(LockMethod).Start();
      new Thread(LockMethod).Start();
      new Thread(SomeOtherMethod).Start();
      Console.WriteLine("Done Main ...");
      Console.ReadLine();
    }

    public static void LockMethod() {
      Console.WriteLine("Enter LockMethod");

      lock(App.lockList) {
        Console.WriteLine("In lock block");
        App.lockList.Add("Software");
        Thread.Sleep(5000);
        App.lockList.Add("Hardware");
      }

      App.PrintList("LockMethod");
      Console.WriteLine("Exit LockMethod");
    }

    public static void SomeOtherMethod() {
      Console.WriteLine("Enter SomeOtherMethod");
      App.lockList.Add("Handy");
      Thread.Sleep(500);
      App.lockList.Add("Kabel");
      Thread.Sleep(500);
      App.lockList.Add("Schlüssel");
      App.PrintList("SomeOtherMethod");
      Console.WriteLine("Exit SomeOtherMethod");
    }

    public static void PrintList(String from) {
      Console.WriteLine(Environment.NewLine + "Print list for " + from);

      lock(App.lockList) {
        foreach(String item in App.lockList) {
          Console.WriteLine(item + " ");
        }
      }

      Console.WriteLine(Environment.NewLine);
    }
  }

Die Ausgabe sieht so aus:

[PRE]
Enter LockMethod
In lock block
Enter LockMethod
Enter SomeOtherMethod
Done Main ...

Print list for SomeOtherMethod
In lock block
Maus
Monitor
Notebook
Software
Handy
Kabel
Schlüssel
Hardware
Software
Hardware


Exit SomeOtherMethod

Print list for LockMethod
Maus
Monitor
Notebook
Software
Handy
Kabel
Schlüssel
Hardware
Software
Hardware


Exit LockMethod

Print list for LockMethod
Maus
Monitor
Notebook
Software
Handy
Kabel
Schlüssel
Hardware
Software
Hardware


Exit LockMethod
[/PRE]

Was ich jetzt nicht verstehe ist, warum ich in der Methode SomeOtherMethod die Liste verändern kann obwohl ich doch in einem Lock-Bereich die Liste "gesperrt" habe. Ist dieses Verhalten damit begründet, weil es sich um einen anderen Thread handelt?
Das lock-Schlüsselwort bewirkt ja, dass immer nur ein Thread in den Block reingeht, was in dem Beispiel ja auch funktioniert, nur dachte ich immer bisher, dass auch das Objekt (hier die Liste) als ganzes gesperrt wird, was aber nicht so ist. Warum sperre ich dann das Objekt, dann müsste doch auch folgendes gehen ...


lock {
  // Do some working
}

Warum muss man explizit ein Objekt sperren und kann nicht, wie z.B. in Java "einfach" nur einen synchronisierten Block (hier also lock ohne Objektangabe) definieren? Kann mich da jemand aufklären?

Vielen Dank für etwaige Antworten schon einaml im Voraus.

Gruß

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo mosspower,

jeder Codeabschnitt der eine Resource teilt muss das entsprechende Lock-Objekt mit lock sichern.
D.h. auch LockMethod und SomeOtherMethod müsen lock(lockList) aufrufen!

[EDIT]
Man muss expliziet ein Objekt sperrren, weil C# verschiedene Sperren gleichzeitig unterstützt. Es kann ja z.B. zwei Listen geben, wenn eine Liste bearbeitet wird, heißt das noch lange nicht, dass die andere Liste auch so lange gesperrt sein muss.

Ach ja: Man soll übrigens immer ein private readonly object für Sperren verwenden, damit nicht irgend ein Fremd-Code der zufällig das Objekt in die Finger bekommt die Sperre nimmt und so ein Dead-Lock verursacht.
[/EDIT]

Gruß
Juy Juka

Gelöschter Account
vor 15 Jahren

Was ich jetzt nicht verstehe ist, warum ich in der Methode SomeOtherMethod die Liste verändern kann obwohl ich doch in einem Lock-Bereich die Liste "gesperrt" habe.

lock bedeutet nciht, das du den zugriff auf das objekt verhinderst (also sperrst). das macht nämlich schon "readonly". lock bedeutet lediglich, das der thread, der lock aufruft, solange geblockt wird, bis die referenz des lockobjektes nicht mehr in der locktabelle steht. das bedeutet, das er sich intern merkt, welche objekte gerade "gelockt" sind u nd wenn ein anderer thread mithilfe von lock versucht dieses objekt nochmals zu sperren, dann wird dieser solange blockiert, bis der thread, der zuvor gesperrt hat, diesen lock wieder freigibt.

in jedem fall muss man immer das schlüsselwort lock verwenden um den zugriff threadsafe zu halten.