2014-02-08 51 views
0

问题描述:需要咨询用于Synchornizing线程

在我的应用程序具有低于类2个线程之间的同步中的一个。

  1. SynchornizingMethods讲座>将由线程1和线程共享2.
  2. DemoClass1 - >通过螺纹简称1
  3. DemoClass2 - >由线程2
  4. SynchornizingDemo.Demo()简称 - >方法是程序的入口点。

预期输出:

线程1(DemoClass1)和线程2(DemoClass2),直到这两个线程完成它们的环在各自的XXXXRun()方法应该平行地延伸。

现状:

程序,当我从我的应用程序调用SynchornizingDemo.Demo()只是挂起。

代码:

public class SynchornizingMethods 
{ 
    static string SharedVariableString = string.Empty; 

    bool threadFlag = true; 

    public void Method1(int inputVal) 
    { 
     lock (this) 
     { 
      if (threadFlag == true) 
      { 
       try 
       { 
        Monitor.Wait(this); 
       } 
       catch (SynchronizationLockException SLE) 
       { 
        SharedVariableString += "\nMethod 1 : " + SLE.Message.ToString(); 
       } 
       catch (ThreadInterruptedException TIE) 
       { 
        SharedVariableString += "\nMethod 1 : " + TIE.Message.ToString(); 
       } 

       SharedVariableString += "\nMethod 1 : " + inputVal; 
       threadFlag = false; 
      } 

      Monitor.Pulse(this); 
     } 
    } 

    public void Method2(int inputVal) 
    { 
     lock (this) 
     { 
      if (threadFlag == false) 
      { 
       try 
       { 
        Monitor.Wait(this); 
       } 
       catch (SynchronizationLockException SLE) 
       { 
        SharedVariableString += "\nMethod 2 : " + SLE.Message.ToString(); 
       } 
       catch (ThreadInterruptedException TIE) 
       { 
        SharedVariableString += "\nMethod 2 : " + TIE.Message.ToString(); 
       } 

       SharedVariableString += "\nMethod 2 : " + inputVal; 
       threadFlag = true; 
      } 

      Monitor.Pulse(this); 
     } 
    } 

    public static void DisplayResult() 
    { 
     MessageBox.Show(SharedVariableString); 
    } 
} 
public class DemoClass1 
{ 
    SynchornizingMethods SyncMethodsObj; 
    public DemoClass1(SynchornizingMethods _SyncMethodsObj) 
    { 
     SyncMethodsObj = _SyncMethodsObj; 
    } 

    public void DemoThread1Run() 
    { 
     // Even Incrementor.    
     for (int lpCnt = 0; lpCnt <= 20; lpCnt += 2) 
     { 
      //Thread.Sleep(10); 
      SyncMethodsObj.Method1(lpCnt); 
     } 
    } 
} 
public class DemoClass2 
{ 
    SynchornizingMethods SyncMethodsObj; 
    public DemoClass2(SynchornizingMethods _SyncMethodsObj) 
    { 
     SyncMethodsObj = _SyncMethodsObj; 
    } 

    public void DemoThread2Run() 
    { 
     // Odd Incrementor. 
     for (int lpCnt = 1; lpCnt <= 20; lpCnt += 2) 
     { 
      //Thread.Sleep(10); 
      SyncMethodsObj.Method2(lpCnt); 
     } 
    } 
} 

public class SynchornizingDemo 
{ 
    public void Demo() 
    { 
     SynchornizingMethods SyncMethodsObj = new SynchornizingMethods(); 

     DemoClass1 DemoClass1Obj = new DemoClass1(SyncMethodsObj); 
     DemoClass2 DemoClass2Obj = new DemoClass2(SyncMethodsObj); 

     try 
     { 
      Thread thread1Obj = new Thread(new ThreadStart(DemoClass1Obj.DemoThread1Run)); 
      Thread thread2Obj = new Thread(new ThreadStart(DemoClass2Obj.DemoThread2Run)); 

      thread1Obj.Start(); 
      thread2Obj.Start(); 

      thread1Obj.Join(); 
      thread2Obj.Join(); 
     } 
     catch (ThreadStateException TSE) 
     { 
      Debug.WriteLine(" Exception Raised SynchornizingDemo : " + TSE.Message.ToString()); 
     } 
     catch (ThreadInterruptedException TIE) 
     { 
      Debug.WriteLine(" Exception Raised SynchornizingDemo : " + TIE.Message.ToString()); 
     } 

     SynchornizingMethods.DisplayResult(); 
    } 
} 
+1

该代码“看起来”不完整,当然不会被任何人编译。你也在说“不按预期工作” - 它如何工作,你会得到什么结果。 – iandotkelly

+0

@iandotkelly,是的,它完成的代码只需要调用SynchornizingDemo.Demo()进行测试,这是我在第一篇文章中提到的,但修改该语句的人被删除并导致混淆。我已经发布了下面的工作计划。 – Sai

回答

0

谢谢大家的提示。我解决了这个问题。它与If条件,我只是用两种方法交换语句。以下是更新的代码。

基本上以下程序的内涵是2个线程将同步共享公共变量,并通过在Demo类中并行运行两个循环来更新一个线程。

 
public class SynchornizingMethods 
    { 
     static string SharedVariableString = string.Empty; 

     bool threadFlag = true; 

     public void Method1(int inputVal) 
     { 
      lock (this) 
      { 
       if (!threadFlag) 
       { 
        try 
        { 
         Monitor.Wait(this); 
        } 
        catch (SynchronizationLockException SLE) 
        { 
         SharedVariableString += "\nMethod 1 : " + SLE.Message.ToString(); 
        } 
        catch (ThreadInterruptedException TIE) 
        { 
         SharedVariableString += "\nMethod 1 : " + TIE.Message.ToString(); 
        } 
       } 

       SharedVariableString += "\nMethod 1 : " + inputVal; 
       Debug.WriteLine("Method 1 : " + inputVal); 
       threadFlag = false; 
       Monitor.Pulse(this); 
      } 
     } 

     public void Method2(int inputVal) 
     { 
      lock (this) 
      { 
       if (threadFlag) 
       { 
        try 
        { 
         Monitor.Wait(this); 
        } 
        catch (SynchronizationLockException SLE) 
        { 
         SharedVariableString += "\nMethod 2 : " + SLE.Message.ToString(); 
        } 
        catch (ThreadInterruptedException TIE) 
        { 
         SharedVariableString += "\nMethod 2 : " + TIE.Message.ToString(); 
        } 
       } 
       SharedVariableString += "\nMethod 2 : " + inputVal; 
       Debug.WriteLine("Method 2 : " + inputVal); 
       threadFlag = true; 

       Monitor.Pulse(this); 
      } 
     } 

     public static void DisplayResult() 
     { 
      MessageBox.Show(SharedVariableString); 
     } 
    } 

    public class DemoClass1 
    { 
     SynchornizingMethods SyncMethodsObj; 

     public DemoClass1(SynchornizingMethods _SyncMethodsObj) 
     { 
      SyncMethodsObj = _SyncMethodsObj; 
     } 

     public void DemoThread1Run() 
     { 
      // Even Incrementor.    
      for (int lpCnt = 0; lpCnt
+0

输出在调试结果:方法1:0 方法2:1 方法1:2 方法2:3 方法1:4 方法2:5 方法1:6 方法2:7 方法1:8 方法2:9 方法1:10 方法2:11 方法1:12 方法2:13 方法1:14 方法2:15 方法1:16 方法2:17 方法1:18方法2:19 线程'CustomThread2'(0x1d54)h如代码0(0x0)所示。 方法1:20方法2:21 线程'CustomThread1'(0x2b4c)已退出,代码为0(0x0)。 是线程1 ActiveFalse 是线程2 ActiveFalse – Sai

0

我觉得你在try块需要Monitor.Wait(这)之前Monitor.Pulse(本)。 我相信它是阻塞的,因为一个线程等待锁并休眠,然后另一个线程休眠而不通知第一个线程锁已准备就绪。

+0

感谢您的分析,但并非如此,在这种情况下,两个线程只会在上述程序中运行一次。由于我的错误条件,它被阻塞。 – Sai

0

您的代码是错误的。可以考虑在for循环的结束发生的事情:

1)线索1具有lpCnt等于20threadFlagtrue。它挂在Monitor.Wait

2)线程2有lpCnt等于19threadFlagtrue所以它只是调用Monitor.Pulse

3)线索1修改字符串,并设置threadFlagfalse。因为这是它的最后一次迭代,所以它完成并存在

4)线程2进入lock。因为没有人可以拨打Monitor.Pulse,所以无限期地等待Monitor.Wait

此外,使用Monitor.WaitMonitor.Pulse“对称”同步两个线程存在已知问题。 documentation说:

Monitor类不维护状态,指示已调用Pulse方法。因此,如果在没有线程正在等待时调用Pulse,则调用Wait的下一个线程阻塞,就像从未调用过Pulse一样。如果两个线程正在使用Pulse和Wait进行交互,则可能导致死锁。将其与AutoResetEvent类的行为进行对比:如果您通过调用其Set方法发出AutoResetEvent指示,并且没有线程在等待,则AutoResetEvent将保持信号状态,直到线程调用WaitOne,WaitAny或WaitAll。 AutoResetEvent释放该线程并返回到无信号状态。

+0

首先感谢您的详细分析。是的,我还注意到您对已知问题强调的一点。不管计数如何,点1 - 4都不会导致程序被挂起而退出线程。我测试了这些步骤并且工作正常。我在if语句中所做的错误,我在下面修复并发布了干净的代码。 – Sai

+1

@SrigopalChitrapu - 测试不是解决同步问题的方法。要确定代码是正确的唯一方法是理解它,因为在测试时竞争条件可能永远不会显示出来。 –

+0

@SrigopalChitrapu第1-4点与这些'if'语句直接相关。如果你改变了他们,并且**似乎**(见上面的Erno的评论)来帮助,那么我写的就是这个原因。 – BartoszKP