すらすらプログラマーへのお問い合わせ
すらすらのブログ
アクセス数  累計:000,125,039  昨日:000,000,099  本日:000,000,061
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 ランキング:ゲーム - キッズ・プレイステーション3】

スレッド処理において一番怖いのがデットロックです。デットロックを起こすとスレッドがフリーズしてしまうため処理が進まなくなり、最悪アプリケーション全体がフリーズしてしまうような状態に陥る危険性があります。
デットロックはどのような状況で発生するのかというと、左図のように、スレッド1は Obj1 ⇒ Obj2 の順でロックして、スレッド2は Obj2 ⇒ Obj1 の順でロックしている場合を想定します。
まずはじめに、スレッド1、スレッド2が同時動いてそれぞれが Obj1, Obj2 をロックします。
スレッド1は次に Obj2 をロックしたいのですが、 すでにスレッド2がロックしているためロック待ち状態になります。一方スレッド2の方も Obj1 をロックしたいのですが、スレッド1にロックされているためこちらもロック待ち状態になってしまいます。
このようにお互いがロックも解除もできない状態になることをデットロックといいます。
この回ではまず、わざとデットロックを起こすプログラムを作成してその仕組みを理解していくことにします。
デットロックを起こすプログラム
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 ロック")
            
SyncLock (_lockObj1)

                Thread.Sleep(1000)

                Console.WriteLine(
"Proc1:Object2 ロック")
                
SyncLock (_lockObj2)

                    Thread.Sleep(1000)

                
End SyncLock
                Console.WriteLine("Proc1:Object2 解除")

                Thread.Sleep(1000)

            
End SyncLock
            Console.WriteLine("Proc1:Object1 解除")

        
Next
    End Sub

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

        
For i As Integer = 0 To 100

            Thread.Sleep(500)

            Console.WriteLine(
"Proc2:Object2 ロック")
            
SyncLock (_lockObj2)

                Thread.Sleep(500)

                Console.WriteLine(
"Proc2:Object1 ロック")
                
SyncLock (_lockObj1)

                    Thread.Sleep(500)

                
End SyncLock
                Console.WriteLine("Proc2:Object1 解除")

                Thread.Sleep(500)

            
End SyncLock
            Console.WriteLine("Proc2:Object2 解除")

        
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 ロック");
                
lock (_lockObj1)
                {
                    
Thread.Sleep(1000);

                    
Console.WriteLine("Proc1:Object2 ロック");
                    
lock (_lockObj2)
                    {
                        
Thread.Sleep(1000);
                    }
                    
Console.WriteLine("Proc1:Object2 解除");

                    
Thread.Sleep(1000);
                }
                
Console.WriteLine("Proc1:Object1 解除");
            }
        }

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

                
Console.WriteLine("Proc2:Object2 ロック");
                
lock (_lockObj2)
                {
                    
Thread.Sleep(500);

                    
Console.WriteLine("Proc2:Object1 ロック");
                    
lock (_lockObj1)
                    {
                        
Thread.Sleep(500);
                    }
                    
Console.WriteLine("Proc2:Object1 解除");

                    
Thread.Sleep(500);
                }
                
Console.WriteLine("Proc2:Object2 解除");
            }
        }
    }
}
実行
作成したプログラムを実行するにはまず、「スレッド1」ボタンをクリックしてスレッド1を走らせます。その後2、3秒まって「スレッド2」ボタンをクリックしてスレッド2を走らせます。
しばらくはスレッド1、スレッド2とも順番に動いていますがしばらくするとデットロックが発生して処理がフリーズします。
デバッグで出力ウィンドウを表示してロック、解除の状態を確認してください。
※このページで紹介しているサンプルコードについて管理者は動作保障をいたしません※
※サンプルコードを使用する場合は、自己責任でお願いします※

【楽天 ランキング:パソコン・周辺機器 - パソコンソフト】




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

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