0

MethodImplOptions.Synchronized メソッド表記のみでデッドロックを再現しようとしています。

using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;

namespace Lab_01
{

    class Program1
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        static void Resource1(int starterIndex, bool startNext = true)
        {
            Console.WriteLine("Resource1 is used ({0})", starterIndex);
            Thread.Sleep(1000);
            if (startNext)
            {
                Resource2(starterIndex, false);
            }
            Console.WriteLine("Resource1 is free ({0})", starterIndex);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        static void Resource2(int starterIndex, bool startNext = true)
        {
            Console.WriteLine("Resource2 is used ({0})", starterIndex);
            Thread.Sleep(1000);
            if (startNext)
            {
                Resource1(starterIndex, false);
            }
            Console.WriteLine("Resource2 is free ({0})", starterIndex);
        }

        static void Main(string[] args)
        {
            Locker locker1 = new Locker();
            Locker locker2 = new Locker();

            new Thread(delegate()
            {
                Resource1(0);
            }).Start();
            new Thread(delegate()
            {
                Resource2(1);
            }).Start();

        }
    }
}

私が期待しているのは

  1. 1 番目のスレッドが開始され、Resource1 メソッドのみがロックされ、1 秒間待機します
  2. 1 番目のスレッドがスリープしている間 (この 1 秒間)、2 番目のスレッドが開始され、2 番目のリソース (Resource2) がロックされます。1 秒間スリープします。
  3. スリープを最初に終了するスレッド、たとえば 1 番目のスレッドは、2 番目のリソースをロックしようとしますが、すでにロックされているためロックできず、2 番目のスレッドが同じ状況にあるため解放できません ( Resource1 をロックしますが、すでにロックされています)。一言で言えば、通常のデッドロック状態です。

しかし、起動するとロックされず、次の出力が得られます。

C:\Users\ginz\C#\19-\Lab_01\Lab_01\bin\Debug>Lab_01.exe
Resource1 is used (0)
Resource2 is used (0)
Resource2 is free (0)
Resource1 is free (0)
Resource2 is used (1)
Resource1 is used (1)
Resource1 is free (1)
Resource2 is free (1)

というわけで、2番めのスレッドは1番めのスレッドが終わったときにだけ開始するのですが、もっと早くから始めるべきだと思います。どうしてこれなの?

この動作はキーワードを使用して簡単に再現できることを知っていますlockが、私の場合、それは不適切な方法です:

            Object obj1 = new Object(), obj2 = new Object();

            new Thread(new ThreadStart(delegate()
            {
                lock (obj1)
                {
                    Thread.Sleep(1000);
                    lock (obj2)
                    {
                        Thread.Sleep(500);
                    }
                }
            })).Start();

            new Thread(new ThreadStart(delegate()
            {
                lock (obj2)
                {
                    Thread.Sleep(1000);
                    lock (obj1)
                    {
                        Thread.Sleep(500);
                    }
                }
           })).Start();

この状況で私を助けていただけませんか?

前もってありがとう、ドミトリー

4

0 に答える 0