すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,683,166  昨日:000,000,189  本日:000,000,004
Loading
スレッド
.NET プログラミング
プロパティグリッド
印刷
リストボックス
スレッド
リストビュー
インストーラー
やってみよう!

できるVisual Studio 2015 Windows /Android/iOS アプリ対応

独習C# 第3版

VisualBasic2013パーフェクトマスター (Perfect Master SERIES)

プログラミング.NET Framework 第4版 (Microsoft Press)

VisualBasic2013逆引き大全555の極意

猫でもわかるWindowsプログラミング 第4版 (猫でもわかるプログラミング)

VisualC#2013逆引き大全555の極意

デットロックの回避 最終更新:2010/07/15
【Amazon ランキング:本 - ゲーム攻略・ゲームブック】

デットロックを回避するには、ロックをネストさせないのが一番の手ですが、どうしても複雑なロック制御を行わないといけない場合はデットロックを防止するため Monitor.TryEntor メソッドを使用してタイムアウトするようにする方法があります。ただしその場合は処理にかかる時間を十分考慮してタイムアウト時間を設定する必要があります。

デットロック時のタイムアウト
Form4 に Button を2つ貼り付けます。
VB[Form4.vb]
Imports System.Threading

Public Class Form4

    
Private _lockObj1 As Object = New Object()
    
Private _lockObj2 As Object = New Object()

    
Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles button1.Click

        
Dim th As Thread = New Thread(AddressOf ThreadProc1)
        th.Start()

    
End Sub

    Private Sub button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        
Handles button2.Click

        
Dim th As Thread = New Thread(AddressOf ThreadProc2)
        th.Start()

    
End Sub

    ' スレッド1処理
    Private Sub ThreadProc1()

        
For i As Integer = 0 To 100

            Thread.Sleep(1000)

            Console.WriteLine(
"Proc1:Object1 ロック")
            
If Monitor.TryEnter(_lockObj1, 1000) Then

                Thread.Sleep(1000)

                
'------------------------------------------
                Console.WriteLine("Proc1:Object2 ロック")
                
If Monitor.TryEnter(_lockObj2, 1000) Then

                    Thread.Sleep(1000)

                    Console.WriteLine(
"Proc1:Object2 解除")
                    Monitor.Exit(_lockObj2)

                
Else
                    Console.WriteLine("Proc1:Object2 ロック失敗!")
                
End If
                '------------------------------------------

                Thread.Sleep(1000)

                Console.WriteLine(
"Proc1:Object1 解除")
                Monitor.Exit(_lockObj1)

            
Else
                Console.WriteLine("Proc1:Object1 ロック失敗!")
            
End If

        Next
    End Sub

    ' スレッド2処理
    Private Sub ThreadProc2()

        
For i As Integer = 0 To 100

            Thread.Sleep(500)

            Console.WriteLine(
"Proc2:Object2 ロック")
            
If Monitor.TryEnter(_lockObj2, 1000) Then

                Thread.Sleep(500)

                
'------------------------------------------
                Console.WriteLine("Proc2:Object1 ロック")
                
If Monitor.TryEnter(_lockObj1, 1000) Then

                    Thread.Sleep(500)

                    Console.WriteLine(
"Proc2:Object1 解除")
                    Monitor.Exit(_lockObj1)

                
Else
                    Console.WriteLine("Proc2:Object1 ロック失敗!")
                
End If
                '------------------------------------------

                Thread.Sleep(500)

                Console.WriteLine(
"Proc2:Object2 解除")
                Monitor.Exit(_lockObj2)

            
Else
                Console.WriteLine("Proc2:Object2 ロック失敗!")
            
End If

        Next
    End Sub

End
 Class
C#[Form4.cs]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadCS
{
    
public partial class Form4 : Form
    {
        
private object _lockObj1 = new object();
        
private object _lockObj2 = new object();

        
public Form4()
        {
            InitializeComponent();
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            
Thread th = new Thread(ThreadProc1);
            th.Start();
        }

        
private void button2_Click(object sender, EventArgs e)
        {
            
Thread th = new Thread(ThreadProc2);
            th.Start();
        }

        
// スレッド1処理
        private void ThreadProc1()
        {
            
for (int i = 0; i < 100; i++)
            {
                
Thread.Sleep(1000);

                
Console.WriteLine("Proc1:Object1 ロック");
                
if (Monitor.TryEnter(_lockObj1, 1000))
                {
                    
Thread.Sleep(1000);

                    
//-------------------------------------
                    Console.WriteLine("Proc1:Object2 ロック");
                    
if (Monitor.TryEnter(_lockObj2, 1000))
                    {
                        
Thread.Sleep(1000);

                        
Console.WriteLine("Proc1:Object2 解除");
                        
Monitor.Exit(_lockObj2);
                    }
                    
else
                    {
                        
Console.WriteLine("Proc1:Object2 ロック失敗!");
                    }
                    
//-------------------------------------

                    Thread.Sleep(1000);

                    
Console.WriteLine("Proc1:Object1 解除");
                    
Monitor.Exit(_lockObj1);
                }
                
else
                {
                    
Console.WriteLine("Proc1:Object1 ロック失敗!");
                }
            }
        }

        
// スレッド2処理
        private void ThreadProc2()
        {
            
for (int i = 0; i < 100; i++)
            {
                
Thread.Sleep(500);

                
Console.WriteLine("Proc2:Object2 ロック");
                
if (Monitor.TryEnter(_lockObj2, 1000))
                {
                    
Thread.Sleep(500);

                    
//-------------------------------------
                    Console.WriteLine("Proc2:Object1 ロック");
                    
if (Monitor.TryEnter(_lockObj1, 1000))
                    {
                        
Thread.Sleep(500);

                        
Console.WriteLine("Proc2:Object1 解除");
                        
Monitor.Exit(_lockObj1);
                    }
                    
else
                    {
                        
Console.WriteLine("Proc2:Object1 ロック失敗!");
                    }
                    
//-------------------------------------

                    Thread.Sleep(500);

                    
Console.WriteLine("Proc2:Object2 解除");
                    
Monitor.Exit(_lockObj2);
                }
                
else
                {
                    
Console.WriteLine("Proc2:Object2 ロック失敗!");
                }
            }
        }
    }
}
実行
作成したプログラムを前回と同じ要領で実行すると、今回はフリーズせずに動作すると思います。時々ロックに失敗するのはデットロックが発生してタイムアウトが発生しているためです。
実際にプログラムを組む場合はタイムアウト発生時にリカバリを行うようにすると良いでしょう。
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:パソコン・周辺機器 - ネットワーク機器】




このサイトはフリーソフトのMerge HTMLで作成されています。
このサイトはリンクフリーです。

ページの先頭に戻る Copyright© 2010-2015 Jun.Shiozaki All rights reserved.