C# 的鎖定與死結

基礎篇

C# 簡介

開發環境

變數與運算

流程控制

陣列

函數

物件

例外處理

函式庫篇

檔案處理

資料結構

正規表達式

Thread

應用篇

視窗程式

媒體影音

網路程式

遊戲程式

手機程式

資料庫

雲端運算

特殊功能

委派

擴展方法

序列化

LinQ

WPF

網路資源

教學影片

投影片

教學文章

軟體下載

考題解答

101習題

簡介

在作業系統的課程當中我們會學到『死結』這個問題,當程式 1 抓住資源 A,卻又在等程式 2 釋放資源 B,而程式 2 則抓住資源 B ,卻又在等程式 1 釋放資源 A 的時候,就會進入死結狀態。下圖顯示了這種死結情況的示意圖。

deadlock.svg

圖一、死結的示意圖

在程式設計中我們真的會遇到死結嗎?如果真的有死結,能否寫一個會造成死結的程式呢?

這並不難,只要用執行緒 (Thread) 與鎖定 (lock) 機制,我們很容易就可以造出會導致死結的程式,以下是我們用 C# 撰寫的一段死結程式,請參考。

using System;
using System.Threading;
using System.Text;

class ThreadTest
{
    static StringBuilder A = new StringBuilder("A");
    static StringBuilder B = new StringBuilder("B");

    public static void Main(String[] args)
    {
        Thread thread1 = new Thread(new ThreadStart(AB));
        Thread thread2 = new Thread(new ThreadStart(BA));
        thread1.Start();
        thread2.Start();
        thread1.Join();
        thread2.Join();
    }

    public static void AB()
    {
        lock (A)
        {
         Console.WriteLine("AB.lock(A)");
         Thread.Sleep(1000);
         lock (B)
         {
         Console.WriteLine("AB.lock(B)");
         }
        }
    }

    public static void BA()
    {
        lock (B)
        {
         Console.WriteLine("BA.lock(B)");
         Thread.Sleep(1000);
         lock (A)
         {
         Console.WriteLine("BA.lock(A)");
         }
        }
    }
}

上述程式的執行結果如下圖所示,當程式跑到 BA.lock(B) 之後就進入了死結,再也無法跑下去了,因此我們不會看到 BA.lock(A) 與 AB.lock(B) 這兩行輸出的結果,程式已經進入了死結狀態,再也出不來了。

CsDeadlockRun.jpg
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License