2016-07-25 12 views
0

私は自分のエラー状況をシミュレートする簡単なプログラムを持っています。私はいくつかのスレッドからメッセージを取得するシングルトンクラスを持っています。関数が実行されるまで実行をブロックする必要があります。マルチスレッドプログラムのLock()

class Program 
{ 
    private static TestClass test; 
    static void Main(string[] args) 
    { 
     Thread a = new Thread(TestFunctionB); 
     a.Start(); 

     Thread b = new Thread(TestFunctionB); 
     b.Start(); 
    } 

    private static void TestFunctionB() 
    { 
     TestClass test = TestClass.Instance; 
     for (int i = 0; i < 15; i++) 
     { 
      test.Handle(i, Thread.CurrentThread.ManagedThreadId); 
     } 
    } 
} 

class TestClass 
{ 
    private readonly object _lockObject; 
    private static TestClass _instance; 

    private TestClass() 
    { 
     _lockObject = new object(); 
    } 

    public static TestClass Instance 
    { 
     get { return _instance ?? (_instance = new TestClass()); } 
    } 

    private void RunLocked(Action action) 
    { 
     lock (_lockObject) 
     { 
      action.Invoke(); 
     } 
    } 

    public void Handle(int counter, int threadId) 
    { 
     Console.WriteLine("\nThreadId = {0}, counter = {1}\n", threadId, counter); 

     RunLocked(() => 
        { 
         Console.WriteLine("\nFunction Handle ThreadId = {0}, counter = {1}\n", threadId, counter); 

         for (int i = 0; i < 30; i++) 
         { 
          Console.WriteLine("Funktion Handle threadId = {0}, counter = {1}, i = {2}", threadId, counter, i); 
          //Thread.Sleep(100); 
         } 

        }); 

     Console.WriteLine("\nFunction Handle free ThreadId = {0}, counter = {1}\n", threadId, counter); 

    } 


} 

`

Iは、スレッドが別の後の出力いずれかを記述することexcpectが、コンソール内のスレッドの出力が混合されます。ロックステートメントが正しくありませんか?

+0

あなたが起こるには何を期待していますか? 'lock'はデリゲートの持続時間を保証します。他のスレッドはそれを取得しませんが、その前または後には何も保証しません。したがって、最初のスレッドは完全なサイクル(30回の反復)を行い、次に2回行います。なんでしょう?単一のメッセージを印刷するには? 1つのスレッドから1つ、別のスレッドから1つ – Sinatr

+0

私は同じことを期待しています。しかしコンソールウィンドウでは、私はf.eを持っています。スレッド1から20文字列、次にスレッド2から12文字列を返します。 – kyy8080

+0

理由は実際にはシングルトンが実装されていない可能性があります。[@Scott](http://stackoverflow.com/a/38571048/1997232)の回答を参照してください。最初は私はこの行動を取っても、あなたは何か違うものを期待しています。 – Sinatr

答えて

1

それはあなたの唯一の問題であるが、get { return _instance ?? (_instance = new TestClass()); }は、あなたが戻った複数のインスタンスで終わる可能性がアトミックでない場合、私は知りません。

は、シングルトンのインスタンスが1つだけ作成されることを保証するためにLazy<T>クラスを使用します。

class TestClass 
{ 
    private readonly object _lockObject; 
    private readonly static Lazy<TestClass> _instance = new Lazy<TestClass>(x=> new TestClass()); 

    private TestClass() 
    { 
     _lockObject = new object(); 
    } 

    public static TestClass Instance 
    { 
     get { return _instance.Value; } 
    } 
    ... 
} 

.NET 4.0以降にアクセスできない場合は、シングルトンの作成をロックする必要があります。

class TestClass 
{ 
    private readonly object _lockObject; 
    private static readonly object _singletonLock = new Object(); 
    private static TestClass _instance; 

    private TestClass() 
    { 
     _lockObject = new object(); 
    } 

    public static TestClass Instance 
    { 
     get 
     { 
      if(_instance == null) 
      { 
       lock(_singletonLock) 
       { 
        if(_instance == null) 
        { 
         _instance = new TestClass(); 
        } 
       } 
      } 
      return _instance; 
     } 
    } 
    ... 
} 
+0

ありがとうございます。それは役に立ちます – kyy8080

+0

答えの横にあるチェックマークをクリックしていただきありがとうございます。 –

関連する問題