多執行緒那些事

2021-07-15 18:40:23 字數 1296 閱讀 3440

其實在所有的軟體開發人員心裡應該有乙個開發準則,那就是錙銖必較。就是對於效能和速度的要求是我們不斷努力的方向。多執行緒就是為了實現我們對計算機硬體的最大化利用和並行處理而提出來的解決方案。當然對效能的要求就帶來了複雜的演算法處理方案。但是其他方面的效能優化也為我們的多執行緒程式設計引入了新的麻煩。首先是我們的記憶體模型。

計算機採用虛擬儲存的記憶體管理方式,其實程式塊只有正在執行時才會調到了記憶體用,由於程式執行過程中的臨時資料是存放在主存(物理記憶體)當中的,這時就存在乙個問題,由於cpu執行速度很快,而從記憶體讀取資料和向記憶體寫入資料的過程跟cpu執行指令的速度比起來要慢的多,因此如果任何時候對資料的操作都要通過和記憶體的互動來進行,會大大降低指令執行的速度。因此在cpu裡面就有了快取記憶體。

當程式處理完資料後會將快取記憶體中的資料重新寫回主存中。為了解決快取不一致性問題,通常來說有以下2種解決方法:

1)通過在匯流排加lock#鎖的方式

簡單說就是計算機的主存的讀寫都是在匯流排上傳輸的,控制器控制著很多電路的閉合,來控制程式的執行。在匯流排上加鎖保證了,在釋放鎖之前,其他執行緒無法使用。

2)通過快取一致性協議

簡單說就是當乙個執行緒更改資料內容時,發現這個資料是乙個共享變數,就會通知其他執行緒他們快取記憶體中的資料已經被更改,從而保證執行緒重新從主存中讀取資料。

原子性:乙個操作要麼不執行要麼執行完畢,在現在的計算機模型中,只有讀寫是原子的操作。特殊情況下32位系統中讀64位的資料也不是原子的。

可見性:就是像前文所說的快取一致性協議,當乙個執行緒更改了資料確保其他執行緒能夠知道共享變數的資料變化。

有序性:同樣是為了追求效能,在執行**是機器會進行指令重排,但是這種規則能夠保證單個執行緒中的依賴關係不會被破壞,但是多執行緒中就可能出現問題。

int i = 0;

boolean flag = false;

i = 1; //語句1

flag = true; //語句2

上面**定義了乙個int型變數,定義了乙個boolean型別變數,然後分別對兩個變數進行賦值操作。從**順序上看,語句1是在語句2前面的,那麼jvm在真正執行這段**的時候會保證語句1一定會在語句2前面執行嗎?不一定,為什麼呢?這裡可能會發生指令重排序(instruction reorder)。

下面解釋一下什麼是指令重排序,一般來說,處理器為了提高程式執行效率,可能會對輸入**進行優化,它不保證程式中各個語句的執行先後順序同**中的順序一致,但是它會保證程式最終執行結果和**順序執行的結果是一致的。

比如上面的**中,語句1和語句2誰先執行對最終的程式結果並沒有影響,那麼就有可能在執行過程中,語句2先執行而語句1後執行。

java多執行緒那些事

多執行緒那些事 0.多執行緒實現兩種方式 1 new thread public void run start 2 new thread new runnable start 推薦第二種,物件導向,1.synchronzied加誰身上鎖住誰,而且還是個悲觀鎖,但是確實能解決多執行緒同步問題,就是效率...

MFC執行緒同步那些事

題目有點大,其實主要講述執行緒執行及退出時遇到的一些問題和解決辦法以及注意事項。乙個工業控制專案,用usb口採集資料,程式結構是主程序負責介面和演算法,建立乙個子執行緒負責usb通訊,讀取資料,死迴圈。參考mfc的執行緒演練編制,以下根據 逐行說明 1.啟動執行緒 用afxbeginthread c...

執行緒池的那些事

一般我們進行執行緒的操作時,往往要建立乙個新的執行緒,執行完畢後再銷毀,等到有新的執行命令時,又得重新建立執行緒,如此一來顯得十分繁瑣,如果我們將之前執行過的執行緒不銷毀而是放入乙個池子中,當需要執行時直接引用它,這就能省下許多操作的步驟與時間,因此不會由於等待建立執行緒而延遲任務的執行,從而提高了...