Laden...

Interlocked und Zuweisung

Erstellt von the_lmich vor 17 Jahren Letzter Beitrag vor 17 Jahren 3.033 Views
the_lmich Themenstarter:in
248 Beiträge seit 2005
vor 17 Jahren
Interlocked und Zuweisung

Hallo,

ich sitze hier gerade in einer hitzigen Diskussion und wollte die Frage mal an die Community weitergeben:

Also es geht um Multithreading, folgender Code: count sei bei Beginn 0.


x = Interlocked.Increment(ref count);

Alsoooo .. g .. ich behaupte, dass Einzige was hier Thread-safe ist, ist der Wert von count, da dieser by ref übergeben wird und im sicheren Context von Interlocked zugewiesen wird. Die Zuweisung zu x hingegen ist nicht sicher, da zwischendurch ein anderer Thread Increment ausgewertet haben könnte. Increment ist statisch und hat keinen Status, daher wird x also nie 1, sondern immer zwei zugewiesen.

Also so:

Thread1: Interlocked.Increment(ref count);
Thread2: Interlocked.Increment(ref count);
Thread1: Zuweisung x (ist 2)
Thread2: Zuweisung x (ist 2)

Was meint Ihr? Thread-safe oder nicht? 🙂 Bin gespannt!

🙂 Torsten

1.373 Beiträge seit 2004
vor 17 Jahren

Hallo,

Meine These: Nach der Rückkehr von Increment befindet sich der Rückgabewert bereits auf dem Stack des jeweiligen Threads. Dieser Wert wird der Variablen x zugewiesen. Dabei wird nicht mehr aus einer Variablen gelesen, die von mehreren Threads aus zugänglich ist. Ein anderer Thread kann also den Wert, den x zugewiesen bekommt, nicht mehr verändern. Die Zuweisung selbst ist demnach threadsicher. Das bedeutet natürlich nicht, dass bei der nächsten Anweisung x noch den gleichen Wert haben muss, da ein anderer Thread bereits seinen Stack-Inhalt nach x geschrieben haben könnte.

Grüße,
Andre

P.S.: Ich glaube, das vorliegende Missverständis ist, dass x nicht den Wert von count zugewiesen bekommt, sondern den Rückgabewert der Methode, welcher sich "sicher" auf dem Thread-eigenen Stack befindet.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo the_lmich,

nicht threadsafe, aber aus einen anderen Grund:

Thread1: Interlocked.Increment(ref count);
Thread2: Interlocked.Increment(ref count);
Thread2: Zuweisung x (ist 3)
Thread1: Zuweisung x (ist 2)

herbivore

M
1.439 Beiträge seit 2005
vor 17 Jahren

Kommt auf x an. Wenn x eine lokale Variable ist, dann schon. Sonst nicht.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo marsgk,

genau andersherum. Es wäre threadsafe, wenn x eine lokale Variable wäre. Oder meintest du es so? Aber es ist ja ohnehin klar, dass lokale Variablen threadsafe sind, also kann man m.E. das Beispiel von the_lmich sinnvollerweise nur so verstehen, dass es sich um eine gemeinsam genutze Variable handelt.

herbivoire

S
8.746 Beiträge seit 2005
vor 17 Jahren

Ob eine Zuweisung (!) thread-safe ist oder nicht hängt vom Typ ab. Alles was letztlich auf 32 Bit abgebildet wird (int, bool, byte, etc.) ist threadsafe. Bei 64-Bit-Systemen geht das dann auch mit 64bit-Typen. Aber was nützt einem eine Zuweisung ohne Abfrage, und die ist niemals thread-safe.

Also kommt man bei Zählern um Interlock-Funktionen o.ä. nicht umhin. Was allerdings geht ist die Kombination von "normaler" Zuweisung und InterlockIncrement/Decrement.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo svenson,

hier geht es ja nicht nur um die Zuweisung, sondern um alle Operationen nach dem Verlassen des geschützten Bereichs, also inbesondere um die return Anweisung und das Verlassen der der Methode inkl. Aufräumen des Stacks. Das sind auch ohne Betrachtung des JITs mehrere Prozessoranweisungen, wo ein Threadwechsel zwischenhauen kann. Die Zuweisung alleine zu betrachten, ist also etwas kurz gesprungen.

herbivore

the_lmich Themenstarter:in
248 Beiträge seit 2005
vor 17 Jahren

Wow,

danke für die rege Teilnahme 🙂

@VizOne:

P.S.: Ich glaube, das vorliegende Missverständis ist, dass x nicht den Wert von count zugewiesen bekommt, sondern den Rückgabewert der Methode, welcher sich "sicher" auf dem Thread-eigenen Stack befindet.

Ist Interlocked nicht statisch? Daher dachte ich, der (Rückgabe-)Wert würde immer aus der Referenz von count gezogen?

@herbivore:
Danke, guter Hinweis!

@All:
Nehmen wir an x sei global und 32-bittig ... ist es nun thread-safe oder nicht? Ein einheitliches Bild konnte ich der Diskussion immer noch nicht entnehmen. Ich denke weiterhin das, was herbivore sagt. Es werden soviele Operationen ausgeführt, dass da schnell mal ein Thread zwischenbügelt. Für mich hat das weiterhin einen faden Beigeschmack. Zudem würde dann auch die Übergabe by ref Sinn machen. Das wäre ja auf jeden Fall sicher.

Danke und Grüße
🙂 Torsten

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo the_lmich,

ich kann mich da nur selbst bestätigen. 🙂 Es ist nicht threadsafe (also in dem Sinne, dass man nicht erwarten kann, dass in x nach den Aufrufen 3 gespeichert ist). Das Beispiel habe ich ja schon geliefert. Und da es keiner widerlegt hat ...

herbivore

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von the_lmich
Nehmen wir an x sei global und 32-bittig ... ist es nun thread-safe oder nicht?

Nochmal: Nicht Variablen sind sicher oder nicht, sondern Operationen. 32-Bit-Zuweisungen sind sicher, alles andere (Addition/Subtraktion/Vergleich) nicht.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo svenson,

bitte verwirr doch the_lmich nicht so. Es geht hier nicht um einzelne Zuweisungen, sondern um den konkreten Code. Du kannst nicht ernsthaft meinen, dass der threadsafe ist.

herbivore

M
1.439 Beiträge seit 2005
vor 17 Jahren

Stimmt,

Kommt auf x an. Wenn x eine lokale Variable ist, dann schon. Sonst nicht. kann viel bedeuten.
Gemeint habe ich natürlich: Wenn x eine lokale Variable ist, dann ist es Thread-safe, sonst nicht.