マルチスレッドプログラミング学習シリーズ---モニターのクラス

コードの一部を見てください:
class Program
{
    static void Main(string[] args)
    {
        //开启两个线程
        var threadOne = new Thread(new ThreadSample("ThreadOne").CountNumbersByLock);
        threadOne.Start();
        var threadTwo = new Thread(new ThreadSample("ThreadTwo").CountNumbersByLock);
        threadTwo.Start();

        //var threadOne = new Thread(new ThreadSample("ThreadOne").CountNumbersByMonitor);
        //threadOne.Start();
        //var threadTwo = new Thread(new ThreadSample("ThreadTwo").CountNumbersByMonitor);
        //threadTwo.Start();
        Console.ReadKey();
    }
}

class ThreadSample
{
    private readonly string _threadNo;
    private readonly static object staticObject = new object();

    public ThreadSample(string threadNo)
    {
        _threadNo = threadNo;
    }

    public void CountNumbersByLock()
    {
        Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
        lock (staticObject)
        {
            Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine($"线程 {_threadNo} is count number..... ");
            
        }
        Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
    }

    public void CountNumbersByMonitor()
    {
        bool isRequiredLock = false;
        try
        {
            Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
            Monitor.Enter(staticObject, ref isRequiredLock);
            Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine($"线程 {_threadNo} is count number..... ");
        }
        finally
        {
            if (isRequiredLock)
            {
                Monitor.Exit(staticObject);
                Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
            }
        }
        
    }
}
コールCountNumbersByLock結果:

画像

コールCountNumbersByMonitor結果:

画像

同じ結果、なぜ?キーロックを監視し、実際にシンタックスシュガーのユースケースのクラスです。ロック効果と同等に
bool isRequiredLock = false;
try
{
    
    Monitor.Enter(staticObject, ref isRequiredLock);
    // code
}
finally
{
    if (isRequiredLock)
    {
        Monitor.Exit(staticObject);
        // code
    }
}
次に、デッドロックの例を見て:
class Program
{
    static void Main(string[] args)
    {
        //开启两个线程
        var threadOne = new Thread(new ThreadSample("ThreadOne").LockA);
        threadOne.Start();
        var threadTwo = new Thread(new ThreadSample("ThreadTwo").LockB);
        threadTwo.Start();
        
        Console.ReadKey();
    }
}

class ThreadSample
{
    private readonly string _threadNo;
    private readonly static object staticObjectA = new object();
    private readonly static object staticObjectB = new object();

    public ThreadSample(string threadNo)
    {
        _threadNo = threadNo;
    }

    public void LockA()
    {
        Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
        lock (staticObjectA)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            lock (staticObjectB)
            {
                Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine($"线程 {_threadNo} is count number..... ");
            }
        }
        Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
    }
    public void LockB()
    {
        Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
        lock (staticObjectB)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            lock (staticObjectA)
            {
                Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine($"线程 {_threadNo} is count number..... ");
            }
        }
        Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
    }

}
結果:

画像

スレッド1と2は、デッドロックの形成に待っていました。
メソッドTryEnterモニタクラスの有効期限は、次のようにデッドロックThreadSampleは、クラスコードを修正避けるために、提供することができます。
class ThreadSample
{
    private readonly string _threadNo;
    private readonly static object staticObjectA = new object();
    private readonly static object staticObjectB = new object();

    public ThreadSample(string threadNo)
    {
        _threadNo = threadNo;
    }

    public void LockA()
    {
        Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
        if(Monitor.TryEnter(staticObjectA,TimeSpan.FromSeconds(3)))
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            if (Monitor.TryEnter(staticObjectB, TimeSpan.FromSeconds(3)))
            {
                Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine($"线程 {_threadNo} is count number..... ");
            }
        }
        Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
    }
    public void LockB()
    {
        Console.WriteLine($"线程 {_threadNo} 等待锁..... ");
        if (Monitor.TryEnter(staticObjectB, TimeSpan.FromSeconds(3)))
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            if (Monitor.TryEnter(staticObjectA, TimeSpan.FromSeconds(3)))
            {
                Console.WriteLine($"线程 {_threadNo} 获取锁..... ");
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine($"线程 {_threadNo} is count number..... ");
            }
        }
        Console.WriteLine($"线程 {_threadNo} 释放锁..... ");
    }

}
デバッグの結果:

画像

上記のコードは、ロック・タイムアウト時間を設定し、3秒以内に、lockObjがロック解除された場合に3秒である、すなわち、3秒後、lockObjはTryEntryメソッド戻り、偽、ロック解除されていない、TryEntryは真を返します。私たちは、デッドロックを避けるために、このメソッドを使用することができます

概要:ロック機能を直接モニターと呼ばれる入力方法と同じです、違いは、最後にロック方式で、それは自動的にロックを解除、およびモニタクラスます、あなただけの場合は、明示的にロックを解除するには、exitメソッドを呼び出す必要があります機能ロック文自体、それはロック文で直接最高です。モニタークラス完全にロック文を()を置き換えることができるだけでなく、あなたはまた、ロック・タイムアウトを設定するにはTryEntryメソッドを使用することができます。

公開された37元の記事 ウォンの賞賛3 ビュー6334

おすすめ

転載: blog.csdn.net/huan13479195089/article/details/88819122