4 Stimmen

Welchen Sinn hat Max(Threading.Interlocked.Increment(Offset), Offset - 1)?

Ich habe das erwähnte Stück Code jetzt schon mehrmals gesehen, was bringt es, eine Max(a+1, a-1) ? Zuerst dachte ich, es könnte sein, um einen Unterlauf zu verhindern, aber es macht nicht wirklich Sinn, den Unterlauf in diesem Fall nicht zu verhindern.

5voto

Vilx- Punkte 100739

Ein bisschen googeln gibt mir einen Verdacht, dass dies von einigen (möglicherweise fehlerhaft) C# zu VB.NET Konverter-Software entstehen könnte. Das würde erklären, das häufige Auftreten der es.

Hinzugefügt: Yessss, ich gefunden ! Versuchen Sie, den folgenden C#-Code einzugeben und in VB.NET zu konvertieren:

int i;
i++;

4voto

Michael Burr Punkte 320591

Wie Sie erwähnt haben, ist es möglich, dass sie versuchen zu erkennen, wann Offset auf Null umschlägt (oder negativ wird) und auf dem Höchstwert für den jeweiligen Typ fixiert bleibt Offset ist. Oder sie versuchen, mit einer Situation umzugehen, in der Offset in mehreren Threads "gleichzeitig" erhöht wird (oder so ähnlich).

In jedem Fall handelt es sich um fehlerhaften Code.

Wenn sie versuchen, einen Umbruch auf Null oder ins Negative zu erkennen bzw. zu verhindern, verursacht eine zu große Schrittweite ohnehin das Problem. Wenn sie versuchen, sich mit Offset gleichzeitig' erhöht werden, bin ich mir nicht sicher, welches Problem sie wirklich zu lösen versuchen oder wie sie es zu lösen versuchen.

Hier sind die Probleme:

Wie Jon Skeet sagt :

Allerdings klingt es immer noch seltsam zu mir - weil, wenn Offset flüchtig ist, der letztere Ausdruck möglicherweise nicht den neuesten Wert sowieso erhalten.

Aber es ist noch schlimmer als das - selbst wenn Offset flüchtig ist, gibt es nichts zu serialisieren, was den neuen Wert von Offset mit einem anderen Thread, der ihn möglicherweise erhöht, so dass der Moment nach der Max() Ausdruck liest den Wert von Offset eine beliebige Anzahl von anderen Threads kann hinzukommen und sie (beliebig oft) erhöhen. Im besten Fall ist der Ausdruck also nutzlos, aber die Verwendung dieser Technik kann schädlich sein, weil Sie am Ende einen Wert von Offset das nicht zu Ihnen "gehört".

Betrachten Sie die Situation, in der Sie Offset um einen Array-Index oder etwas anderes zu verfolgen (was angesichts des Namens genau nach dem klingt, was vor sich gehen könnte). Wenn Sie atomar inkrementieren Offset wird das Array-Element mit diesem Index für Sie verfügbar. Wenn Sie die Max() Ausdruck wie in der Frage können Sie plötzlich auf einem Array-Element herumtrampeln, das eigentlich zu einem anderen Thread gehört.

Ich kann mir keinen legitimen Grund vorstellen, um die

Max(Threading.Interlocked.Increment(Offset), Offset - 1)

Wie ich schon sagte, ist es bestenfalls harmlos (und nutzlos), aber es könnte zu sehr schwer zu diagnostizierende Probleme - verwenden Sie es nicht .


Dank des Kommentars von Simon Svensson, der auf eine Google-Suche nach der Verwendung in der Frage hinwies, sieht es so aus, als ob dieser Code normalerweise (immer?) von der Ausgabe eines C#-zu-VB.NET-Konverters stammt. Er verwendet diesen Ausdruck sogar zur Inkrementierung lokaler Variablen (Threading ist also kein Problem). In den Fällen, in denen Offset eine lokale Variable ist, fällt dieser Ausdruck in die nutzlose, aber meist harmlose Sorte (es gibt einen "Fehler", wenn das Inkrement umbricht). Es ist eigentlich mehr oder weniger eine sehr ineffiziente Offset++ Ausdrucks (tatsächlich scheint es die Art und Weise zu sein, wie der Konverter den C#-Ausdruck umwandelt Offset++ zu VB.NET - siehe http://www.telerik.com/community/forums/open-source-projects/code-converter/added-value.aspx#307755 ). Eigentlich ist diese Umwandlung fehlerhaft für Offset++ zurück, weil es den inkrementierten Wert zurückgibt, obwohl es den Wert vor der Inkrementierung zurückgeben sollte.

Das wirklich Schlimme daran ist, dass andere Leute sich diesen Code ansehen und denken könnten: "So muss ich das also verwenden Interlocked.Increment() ".

2voto

Jon Skeet Punkte 1325502

Nun, das ist nicht dasselbe wie Max(a, a-1) - denn es gibt die Aufforderung Interlocked.Increment . Angenommen, ein anderer Thread ändert den Wert von Offset zwischen dem Aufruf von Interlocked.Increment und die Bewertung von Offset-1 .

Dennoch kommt mir das seltsam vor - denn wenn nicht Offset flüchtig ist, erhält der letztgenannte Ausdruck möglicherweise ohnehin nicht den neuesten Wert.

Nach all dem kann der Code nicht ziemlich sein

Math.Max(Interlocked.Increment(Offset), Offset-1)

weil der Parameter für Interlocked.Increment es un ref Parameter. Der nächstliegende legale Code wäre der folgende:

Math.Max(Interlocked.Increment(ref Offset), Offset-1)

(Das wäre immer noch seltsam, da es eine Variable in Pascal-Grundform bedeutet...)

Wenn Sie vielleicht den genauen Code zeigen könnten im Zusammenhang könnten wir den Punkt ausarbeiten. Ich kann nicht behaupten, dass ich selbst jemals einen solchen Code gesehen habe.

1voto

rpetrich Punkte 32030

Interlocked.Increment(a) inkrementiert den Wert von a atomar. In einer Single-Thread-Anwendung ist es äquivalent zu a++ ist aber etwas langsamer. In einer Multithreading-Anwendung stellt es sicher, dass beide Threads den Wert erhöhen, ohne sich gegenseitig zu behindern. Siehe die MSDN-Referenzseite für weitere Einzelheiten

Warum es in diesem Zusammenhang verwendet wird, kann ich nicht sagen, ohne mehr Code zu sehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X