C#-多執行緒資料同步容易出現的異常問題

蓬萊仙羽發表於2016-09-27

問題描述:

當多個執行緒同時併發讀寫資料庫的時候會丟擲異常,這是比較典型的多執行緒併發同步所帶來的問題,因為集合在讀的過程中是不容許我們修改的,因此就需要引入鎖的概念,加上讀寫鎖就不會出現問題。


集合類通常不是執行緒安全的,多個閱讀器可以安全的讀取集合.但是對集合的任何修改都將為訪問集合的所有執行緒生成不明確的結果.使用以下任何方法都可以令集合類是執行緒安全的
(1) 使用Synchronized 方法,則從該類派生包裝,並通過該包裝以獨佔方式訪問集合
(2) 如果該類沒有Synchronized 方法,則從該類派生並使用SyncRoot屬性實現Synchronized 方法.
(3) 在訪問該集合時對SyncRoot屬性使用鎖定機制
這一段時間在公司做多執行緒的東西比較多,所以把一些心得寫了下來,對關注這一塊的朋友有個提示作用.
大家可以看看以下程式碼:

  class Program
    {
        static void Main(string[] args)
        {
            Program pg = new Program();
            //寫執行緒
            Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));
            // 讀執行緒
            Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));
            //刪執行緒
            Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));
            t1.Start();
            t2.Start();
            t3.Start();
        }
        ArrayList arraylist = new ArrayList();
        public void t1fun()
        {
            while (true)
            {
                arraylist.Add("t1--寫入");
                System.Console.Out.WriteLine("寫入");
                System.Threading.Thread.Sleep(1000);
            }
        }
        public void t2fun()
        {
            while (true)
            {
                for (int i = arraylist.Count - 1; i >= 0; i--)
                {
                    System.Console.Out.WriteLine("t2讀取:"+(string)arraylist[i]);
                }
                System.Threading.Thread.Sleep(1000);
            }
        }
        public void t3fun()
        {
            while (true)
            {
                for (int i = arraylist.Count - 1; i >= 0; i--)
                {
                    arraylist.RemoveAt(i);
                    System.Console.Out.WriteLine("t3刪除:t1"+i.ToString());
                }
                System.Threading.Thread.Sleep(1000);
            }
        }
    }

這個測試程式得簡單,大家一看就明白了你可以執行一下看看,程式一會就掛了,揭示異常:未處理的異常: System.ArgumentOutOfRangeException: 索引超出範圍。必須為非負值並小於集合大小。
這就是因為多執行緒中對共享的集合資源同步引起的
下面是改後的程式碼:

 class Program
    {
        static void Main(string[] args)
        {
            Program pg = new Program();
            //寫執行緒
            Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));
            // 讀執行緒
            Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));
            //刪執行緒
            Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));
            t1.Start();
            t2.Start();
            t3.Start();
        }
        ArrayList arraylist = new ArrayList();
        public void t1fun()
        {
            while (true)
            { 
                lock (arraylist.SyncRoot)
                {
                    arraylist.Add("t1--寫入");
                }
                System.Console.Out.WriteLine("寫入");
                System.Threading.Thread.Sleep(1000);
            }
        }
        public void t2fun()
        {
            while (true)
            {
                lock (arraylist.SyncRoot)
                {
                    for (int i = arraylist.Count - 1; i >= 0; i--)
                    {
                        System.Console.Out.WriteLine("t2讀取:" + (string)arraylist[i]);
                    }
                }
                System.Threading.Thread.Sleep(1000);
            }
        }
        public void t3fun()
        {
            while (true)
            {
                lock (arraylist.SyncRoot)
                {
                    for (int i = arraylist.Count - 1; i >= 0; i--)
                    {
                        arraylist.RemoveAt(i);
                        System.Console.Out.WriteLine("t3刪除:t1" + i.ToString());
                    }
                }
                System.Threading.Thread.Sleep(1000);
            }
        }
    }


相關文章