C#多線程List的非執行緒安全性

來源:互聯網
上載者:User

標籤:resolve   一個   原因   size   thread   att   alt   tor   down   

背景:最近在做多線程方面的工作,工作中發現多線程中很多坑,這裡就有一個List添加對象的誤區,這裡做個分享跟大家講講這個坑是怎麼形成的怎麼樣避免。

樣本:

代碼及錯誤:

如果單單只從程式邏輯上看,應該沒有邏輯錯誤,但是結果卻是是有為空白值的情況,這時候有些多線程經驗的讀者可能會想到,建構函式也是一個函數,有可能在往List中添加對象的時候,建構函式還沒有將對象返回就執行了添加操作,造成了這個問題的出現,下面我們來驗證一下這個觀點是否正確。

可以看到,在對象new之後立即執行了取屬性操作,如果建構函式沒有返回立即執行後面肯定會出現null 指標異常,但是這裡並沒有出問題,說明不是建構函式返回結果的問題,同時也說明了建構函式是具有安全執行緒的。

為此可以懷疑這個問題是優於List.Add方法造成的,為此,查看一下List.Add方法的源碼可以瞭解其中的原委。

點開this.EnsureCapacity(this.size+1);方法,如所示:

這時候,我們就可以猜測到問題就出現在這個容量擴充方法這裡了,於是我嘗試著修改List的最初容量,使之不需要進行容量擴充,此時程式運行正常,說明問題的確就在這裡。

雖然說問題解決了,問題的原因也知道了,但是為什麼會有這樣的問題呢?記憶體擴容是如何形成這個錯誤的呢,於是和六爺討論了一下這個問題,很感謝六爺指點迷津,讓我知道了這其中的具體原因,我畫個簡圖給大家講解一下,希望大家能看明白:

驗證:

假設真的是這個原因造成的應該出現空值的位置應該都是2的整數次冪之後的值,並且如果記憶體越大拷貝的時間越長,出現空值的幾率就越大,於是改造程式,可以驗證六爺的這個猜測:

代碼:

結果,8192=4096*2,16384=8192*2:

解決方案:

1.擴容List的初始容量為集合需要的實際容量或更大

2.給List.Add方法加鎖

3.使用List的安全執行緒版本,如所示:

原始碼:

C#多線程List的非執行緒安全性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.