2016-07-31 6 views
-1

Ich erstelle ein Beispiel über Thread,
Ich weiß, dass Verwendung Sperre Thread am kritischen Abschnitt Suspendierung vermeiden konnte, aber ich habe zwei Fragen.

1. Warum mein Programm stecken bleiben, wenn ich Thread.Sleep verwende?
In diesem Beispiel füge ich zwei Threads Schlaf hinzu.
Weil ich möchte, dass die Konsole langsamer ausgibt, damit ich leicht sehen kann, ob etwas falsch ist.
Aber wenn ich Thread.Sleep() verwende, dann wird dieses Programm stecken bleiben!Verwendung von Thread.Sleep in Sperrabschnitt C#

2.Welche Situation sollte ich Thread.Sleep verwenden?

Vielen Dank für Ihre freundliche Antwort, einen schönen Tag.

class MyThreadExample 
{ 
    private static int count1 = 0; 
    private static int count2 = 0; 
    Thread t1; 
    Thread t2; 
    public MyThreadExample() { 
     t1 = new Thread(new ThreadStart(increment)); 
     t2 = new Thread(new ThreadStart(checkequal)); 
    } 
    public static void Main() { 

     MyThreadExample mt = new MyThreadExample(); 
     mt.t1.Start(); 
     mt.t2.Start(); 

    } 
    void increment() 
    { 
     lock (this) 
     { 
      while (true) 
      { 
       count1++; count2++; 
       //Thread.Sleep(0); stuck when use Sleep! 
      } 
     } 
    } 
    void checkequal() 
    { 
     lock (this) 
     { 
      while (true) 
      { 
       if (count1 == count2) 
        Console.WriteLine("Synchronize"); 
       else 
        Console.WriteLine("unSynchronize"); 
       // Thread.Sleep(0); 
      } 
     } 
    } 
} 
+0

Erklärung für Thread.Sleep (0): http://stackoverflow.com/questions/3257708/thread-sleep0-what-is- das-normal-verhalten –

+0

aber stecken bleibt immer noch wenn ich Thread.Sleep (10/100/1000 ...) verwende – AHao

+0

Dein Programm wird immer hängen bleiben. Wo es hängen bleibt, ist völlig zufällig, einer der Threads wird zuerst in die Sperre eintreten und der andere Thread wird niemals in die Sperre eintreten. Es ist etwas wahrscheinlicher, "Synchronisieren" ohne den Aufruf von Sleep() zu sehen, da der Jitter den Code schneller generieren kann. Aber natürlich ändern sich die count1 und count2 Werte nie. Verwenden Sie keine Threads, wenn dies noch nicht offensichtlich ist, sollten Sie das Thema viel gründlicher studieren. –

Antwort

0

Bitte sehen Sie sich die folgenden Codes an. Benutze niemals lock (this), stattdessen benutze lock (syncObj), weil Du eine bessere Kontrolle darüber hast. Sperren Sie nur den kritischen Bereich (zB: nur Variable) und sperren Sie nicht die gesamte While-Schleife. Fügen Sie in der Methode Main etwas hinzu, um am Ende "Console.Read()" zu warten, andernfalls ist Ihre Anwendung tot. Dieser arbeitet mit oder ohne Thread.Sleep. In Ihrem obigen Code wird Ihr Thread "Increment" oder "Checkequal" eingeben und das Schloss wird niemals freigegeben. Deshalb funktioniert es nur bei Increment oder Checkequal und niemals bei beiden.

internal class MyThreadExample 
    { 
    private static int m_Count1; 
    private static int m_Count2; 
    private readonly object m_SyncObj = new object(); 
    private readonly Thread m_T1; 
    private readonly Thread m_T2; 

    public MyThreadExample() 
    { 
     m_T1 = new Thread(Increment) {IsBackground = true}; 
     m_T2 = new Thread(Checkequal) {IsBackground = true}; 
    } 

    public static void Main() 
    { 
     var mt = new MyThreadExample(); 
     mt.m_T1.Start(); 
     mt.m_T2.Start(); 
     Console.Read(); 
    } 

    private void Increment() 
    { 
     while (true) 
     { 
     lock (m_SyncObj) 
     { 
      m_Count1++; 
      m_Count2++; 
     } 
     Thread.Sleep(1000); //stuck when use Sleep! 
     } 
    } 

    private void Checkequal() 
    { 
     while (true) 
     { 
     lock (m_SyncObj) 
     { 
      Console.WriteLine(m_Count1 == m_Count2 ? "Synchronize" : "unSynchronize"); 
     } 
     Thread.Sleep(1000); 
     } 
    } 
    } 

Thread ist ein bisschen altmodisch. Wenn Sie ein Anfänger von .NET sind und .NET 4.5 oder höher verwenden, dann verwenden Sie Aufgabe. Viel besser. Alle neuen Multithreading in .NET basieren auf Aufgabe, wie async erwarten:

public static void Main() 
{ 
    var mt = new MyThreadExample(); 
    Task.Run(() => { mt.Increment(); }); 
    Task.Run(() => { mt.Checkequal(); }); 
    Console.Read(); 
} 
+0

Danke, ich verstehe jetzt, was der wirklich kritische Bereich ist, aber darf ich fragen, warum "syncObj" statt "this" gesperrt wird? Was ist das anders? Obwohl ich das in Büchern gelesen habe, verstehe ich diesen Teil nicht wirklich. – AHao

+0

Bessere Erklärung über Schloss (das), warum es schlecht ist: http://StackOverflow.com/Questions/251391/Why-is-Lockthis-bad –

+0

Danke! By the way, danke für dein Beispiel mit kleiner Ausgabe, wie Isbackground-Eigenschaft, sie helfen mir sehr. – AHao