日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理

發(fā)布時間:2023/12/15 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 學(xué)習(xí)多線程知識的根本目標(biāo)

多線程知識的根本目標(biāo)是:設(shè)計穩(wěn)健的并發(fā)程序。

當(dāng)然,本文無法回答這個實踐性很強的問題(這與具體的業(yè)務(wù)相關(guān),涉及到具體的策略),本文主要闡述相關(guān)知識之間的關(guān)系,希望初學(xué)者不要迷失在多線程工具類的API接口中。

2 并發(fā)程序的三大宏觀問題

線程安全性問題、性能問題、活躍性問題。 三者的關(guān)系是,在設(shè)計并發(fā)程序過程中要首先保證線程安全,在線程安全的基礎(chǔ)上努力提升程序性能,在保證線程安全與提升性能時避免引入活躍性問題。

線程安全是最重要的,設(shè)計并發(fā)程序是為了提升程序的性能,但是永遠不要忘記性能是建立在安全的基礎(chǔ)上的;而在保證安全性(如加鎖、同步等方法)及優(yōu)化并發(fā)性能(如通過鎖分解、鎖分段等方法)過程中,可能會引入活躍性問題(如死鎖、饑餓、活鎖、糟糕的響應(yīng)性等問題)。 本文主要闡述線程安全問題的知識。

3 線程安全性

3.1 線程安全性的定義

當(dāng)多個線程訪問某個類時,這個類始終都能表現(xiàn)出正確的行為,那么就稱這個類是線程安全的。最核心的概念就是正確性。正確性的含義是,某個類的行為與其規(guī)范完全一致。

就像你要設(shè)計一道菜,那么組成這道菜的食材和調(diào)料一定是可控的,即你能確切的描述對這些食材和調(diào)料操作的結(jié)果,比如放油菜會香,放鹽菜會咸,并且知道菜快熟時再放鹽,只有對構(gòu)成這道菜的所有元素都清楚明晰,設(shè)計出的菜才符合設(shè)想。設(shè)計程序時也一樣,只有使用的各個變量和函數(shù)是可控的,設(shè)計出的程序才能按照設(shè)計運行。而多線程的使用,可能會使得組成程序的某些變量和行為變得不可控。

3.2 為什么多線程會帶來線程安全性問題

要闡明線程安全性問題需要深入到JAVA內(nèi)存模型,這里暫時不引入,這里用兩個生活中的例子來闡述線程安全性問題的本質(zhì)(原子性問題和可見性問題)。

【例1】以炒菜為例。其中有個操作是放鹽,放鹽的操作可分解為三個步驟“找到鹽罐→檢查鹽罐裝的是鹽→菜快熟的時候?qū)Ⅺ}倒入菜中”。如果只有一個人在使用鹽罐,那么不會有什么問題。但是,如果在你“檢查鹽罐中裝的是鹽”之后,將鹽倒入菜中之前,另一個人拿走了鹽罐,裝了三氯氰胺奶粉,然后將鹽罐放回。這個調(diào)換過程你并不知道,最后你將調(diào)換過的三氯氰胺奶粉倒入了菜中,結(jié)果可想而知。這就是線程安全性問題的原子性問題。

從內(nèi)存模型理解原子性問題:juejin.im/post/684490…

【例2】以A和B協(xié)作煮米飯為例。有三個房間(廚房、控火室、觀察室),廚房有個鍋煮著米飯(鍋上有張紙寫著“已熟”或者“未熟”),A在控火室負(fù)責(zé)關(guān)火(當(dāng)看到鍋上的紙寫著“已熟”時關(guān)火),B在觀察室負(fù)責(zé)觀察米的狀態(tài)并修改鍋上貼紙的狀態(tài)字(已熟/未熟);A和B不在一個房間,無法直接交流;B隔一會觀察下鍋里的米,如果米熟了就在一張紙上寫“已熟”,未熟就寫“未熟”,B很忙,寫完字后將紙貼在了自己門上,未貼在廚房的鍋上。最終結(jié)果是,A看到鍋上的狀態(tài)字一直是“未熟”,所以不關(guān)火,最終米飯糊了。這就是可見性問題。

從內(nèi)存模型理解可見性問題:juejin.im/post/684490…

3.3 解決原子性問題和內(nèi)存可見性的核心

要編寫線程安全的代碼,其核心在于要對狀態(tài)(變量)訪問操作進行管理,特別是對共享的和可變的狀態(tài)的訪問。

共享意味著可由多個線程訪問操作,可變意味著可以被修改。

上述例1中,如果鹽罐不共享即其他人不能使用,則不會有線程安全性問題。如果規(guī)定不能往鹽罐中裝入,只能從鹽罐中取出,那么不管多少個人可以操作鹽罐,鹽罐中始終是鹽,沒有線程安全性問題;同樣,如果一個變量不能被修改,那么不管多少個線程操作這個變量,也不會帶來線程安全性問題。

上述例2中,如果強制B在修改狀態(tài)字后,將紙貼在鍋上,那么就可以讓A看到米飯的真正狀態(tài),就可以及時關(guān)掉火,蒸出香噴噴的米飯。

那么,為了解決原子性問題和內(nèi)存可見性問題,怎么對共享的且可變的變量進行管理?

除非需要某個域是可變的,否則應(yīng)將其聲明為final域(即聲明為不可變的)

將對共享變量的并行操作轉(zhuǎn)換為串行操作(如同步機制、將變量委托給同步容器進行管理)

將共享變量轉(zhuǎn)換為不共享變量(如線程封閉(棧封閉、ThreadLocal類等))

如果某個操作需要以原子方式執(zhí)行,那么就想辦法保證這個操作是原子方式執(zhí)行(如給操作加鎖)

對于需要保證內(nèi)存可見性的變量,可以強制線程從主內(nèi)存而不是緩存中讀取變量,在線程存儲變量時強制存取到主內(nèi)存中。(如加鎖,聲明volatile變量)

切記,核心是管理共享的可變狀態(tài),鎖(內(nèi)置鎖、Lock鎖)、同步容器類(Vector、Hashtable等)、并發(fā)容器類(ConcurrentHashMap、CopyOnWriteArrayList)、同步工具類(閉鎖、信號量、柵欄)、線程池等都只是是管理共享的可變狀態(tài)的工具。

總結(jié)

以上是生活随笔為你收集整理的java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。