2009-03-25 13 views
6

Wenn zwei Threads zum gleichen Zeitpunkt eine statische Funktion aufrufen, gibt es ein Parallelitätsrisiko? Und wenn diese Funktion ein statisches Mitglied der Klasse verwendet, gibt es sogar ein größeres Problem?Statische Funktion Parallelität ASP.NET

  • Sind die beiden Anrufe voneinander getrennt? (Die Funktion ist wie für die beiden Threads kopiert?)
  • Sind sie automatisch in die Warteschlange eingereiht?

Zum Beispiel gibt es im nächsten Beispiel ein Risiko?

private static int a = 5; 

public static int Sum() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

Und nächstes Beispiel, gibt es ein Risiko?

public static int Sum2() 
{ 
    int a = 5; 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

Update: Und in der Tat, wenn beide Funktionen in der gleichen Klasse sind, was ist das Risiko dann?

thx, Lieven Cardoen

Antwort

10

Ja, es ist eine Gleichzeitigkeit Risiko, wenn Sie eine statische Variable in statischen Methoden ändern.

Die statischen Funktionen selbst haben unterschiedliche Gruppen von lokalen Variablen, aber alle statischen Variablen werden gemeinsam genutzt.

In Ihren spezifischen Beispielen werden Sie nicht angezeigt, aber das liegt nur daran, dass Sie Konstanten verwenden (und ihnen dieselben Werte zuweisen). Ändern Sie das Codebeispiel leicht und Sie werden ausgesetzt.

Edit:

Wenn Sie beide Summe1() aufrufen und Sum2() von verschiedenen Threads Sie in Schwierigkeiten sind, gibt es keine Möglichkeit, den Wert von a und b in dieser Aussage zu gewährleisten: int c = a + b;

private static int a = 5; 

public static int Sum1() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

public static int Sum2() 
{ 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

Sie können auch Concurrency Probleme mit mehreren Anrufungen aus einer einzigen Methode wie dieses Ziel zu erreichen:

public static int Sum3(int currentA) 
{ 
    a = currentA; 
    int b = 4; 
    int c = a + b; 
    int d = a * b; // a may have changed here 
    return c + d; 
} 

Das Problem hierbei ist, dass der Wert von a kann durch andere Mittelmethode ändern Aufrufe ändern es.

+0

ich zum ersten Beispiel geändert. Jetzt ist es wahrscheinlich nicht mehr threadsicher? –

+0

Gibt es gute Referenzen, Bücher, Links zu diesem Thema + Wie können Sie mit diesen Situationen umgehen? –

+0

http://www.amazon.com/Concurrent-Programming-Java-TM-Principles/dp/0201310090/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1237967873&sr=8-3 sollte Ihnen gut dienen – krosenvold

1

In Ihren beiden Beispielen gibt es keine Threadsicherheitsprobleme, da jeder Aufruf der Funktion eine eigene Kopie der lokalen Variablen auf dem Stack hat und in Ihrem ersten Beispiel mit 'a' eine statische Variable ist Ändere 'a', also gibt es kein Problem.

Wenn Sie den Wert in 'a' in Ihrem ersten Beispiel ändern, haben Sie ein mögliches Nebenläufigkeitsproblem.

+0

Wahr, bemerkte nicht, dass Variable A nicht geändert wird, also ist alles gut in dem Code, den wir sehen können. Möglicherweise könnte es außerhalb des sichtbaren Codes geändert werden –

+0

Geändert. Es tut uns leid. Das erste Beispiel war nicht so gut. –

1

Wenn der Umfang der Variablen innerhalb der statischen Funktion enthalten ist, dann gibt es kein Risiko, sondern Variablen außerhalb des Funktionsumfangs (statisch/shared) stellen definitly eine Gleichzeitigkeit Risiko

3

Ja, es ist ein Risiko. Aus diesem Grund sehen Sie in MSDN-Dokumenten oft "Diese Klasse ist für statische Elemente threadsafe" (oder so ähnlich).Das bedeutet, wenn MS den Code geschrieben hat, haben sie absichtlich Synchronisationsgrundelemente verwendet, um die statischen Mitglieder threadsicher zu machen. Dies ist beim Schreiben von Bibliotheken und Frameworks üblich, da es einfacher ist, statische Member threadsicher als Instanzmember zu machen, weil Sie nicht wissen, was der Bibliotheksbenutzer mit Instanzen machen möchte. Wenn sie Instanzmitglieder für viele Bibliotheksklassen threadsafe machen würden, würden sie dir zu viele Beschränkungen auferlegen ... so oft lassen sie dich damit umgehen.

Also müssen Sie auch Ihre statischen Mitglieder threadsafe machen (oder dokumentieren, dass sie nicht sind).

Übrigens, statische Konstruktoren sind threadsafe in gewissem Sinne. Die CLR stellt sicher, dass sie nur einmal aufgerufen werden und verhindert, dass zwei Threads in einen statischen Konstruktor gelangen.

EDIT: Marc wies in den Kommentaren auf einen Randfall hin, in dem statische Konstruktoren nicht threadsicher sind. Wenn Sie einen statischen Konstruktor explizit mit Reflection aufrufen, können Sie ihn scheinbar mehrmals aufrufen. Daher überarbeite ich die Anweisung wie folgt: Solange Sie sich darauf verlassen, dass die CLR entscheidet, wann Sie Ihren statischen Konstruktor aufrufen sollen, verhindert die CLR, dass sie mehrmals aufgerufen wird, und verhindert, dass der statische ctor aufgerufen wird zurückhaltend.

+0

Eigentlich nein, es garantiert * das nicht - Sie können den Typ-Initialisierer über die Reflexion trivial aufrufen, in diesem Fall können Sie es mehrfach gleichzeitig aufrufen. –

+0

Ah, interessant. Daran habe ich nie gedacht. Guter Punkt.Solange Sie es jedoch vermeiden, es explizit durch Reflektion aufzurufen, können Sie sich darauf verlassen, dass die CLR es threadsicher macht. Das ist manchmal nützlich. –

3

Weitere Informationen zu lokalen Variablen finden Sie unter here. vor Ihrer Bearbeitung keine der oben genannten Methoden selbst präsentiert ein Nebenläufigkeitsrisiko; die lokalen Variablen sind alle unabhängig voneinander; Der gemeinsame Status (static int a) ist für mehrere Threads sichtbar, aber Sie mutieren ihn nicht und Sie lesen ihn nur einmal.

Wenn haben Sie so etwas wie:

if(a > 5) { 
    Console.WriteLine(a + " is greater than 5"); 
} // could write "1 is greater than 5" 

wäre es (theoretisch) nicht sicher sein, da der Wert eines von einem anderen Thread geändert werden könnte - Sie würden entweder der Regel Zugang synchronisieren (über lock usw.) oder einen Schnappschuss machen:

Wenn Sie den Wert bearbeiten, würden Sie fast sicher eine Synchronisierung benötigen.

+0

Thx. Entschuldigung für die Bearbeitung. –

1

Statische Methoden in OO unterscheiden sich nicht von "nur" Funktionen in der prozeduralen Programmierung. Wenn Sie keinen Zustand innerhalb einer statischen Variablen speichern, besteht kein Risiko.