java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理
1 學習多線程知識的根本目標
多線程知識的根本目標是:設計穩健的并發程序。
當然,本文無法回答這個實踐性很強的問題(這與具體的業務相關,涉及到具體的策略),本文主要闡述相關知識之間的關系,希望初學者不要迷失在多線程工具類的API接口中。
2 并發程序的三大宏觀問題
線程安全性問題、性能問題、活躍性問題。 三者的關系是,在設計并發程序過程中要首先保證線程安全,在線程安全的基礎上努力提升程序性能,在保證線程安全與提升性能時避免引入活躍性問題。
線程安全是最重要的,設計并發程序是為了提升程序的性能,但是永遠不要忘記性能是建立在安全的基礎上的;而在保證安全性(如加鎖、同步等方法)及優化并發性能(如通過鎖分解、鎖分段等方法)過程中,可能會引入活躍性問題(如死鎖、饑餓、活鎖、糟糕的響應性等問題)。 本文主要闡述線程安全問題的知識。
3 線程安全性
3.1 線程安全性的定義
當多個線程訪問某個類時,這個類始終都能表現出正確的行為,那么就稱這個類是線程安全的。最核心的概念就是正確性。正確性的含義是,某個類的行為與其規范完全一致。
就像你要設計一道菜,那么組成這道菜的食材和調料一定是可控的,即你能確切的描述對這些食材和調料操作的結果,比如放油菜會香,放鹽菜會咸,并且知道菜快熟時再放鹽,只有對構成這道菜的所有元素都清楚明晰,設計出的菜才符合設想。設計程序時也一樣,只有使用的各個變量和函數是可控的,設計出的程序才能按照設計運行。而多線程的使用,可能會使得組成程序的某些變量和行為變得不可控。
3.2 為什么多線程會帶來線程安全性問題
要闡明線程安全性問題需要深入到JAVA內存模型,這里暫時不引入,這里用兩個生活中的例子來闡述線程安全性問題的本質(原子性問題和可見性問題)。
【例1】以炒菜為例。其中有個操作是放鹽,放鹽的操作可分解為三個步驟“找到鹽罐→檢查鹽罐裝的是鹽→菜快熟的時候將鹽倒入菜中”。如果只有一個人在使用鹽罐,那么不會有什么問題。但是,如果在你“檢查鹽罐中裝的是鹽”之后,將鹽倒入菜中之前,另一個人拿走了鹽罐,裝了三氯氰胺奶粉,然后將鹽罐放回。這個調換過程你并不知道,最后你將調換過的三氯氰胺奶粉倒入了菜中,結果可想而知。這就是線程安全性問題的原子性問題。
從內存模型理解原子性問題:juejin.im/post/684490…
【例2】以A和B協作煮米飯為例。有三個房間(廚房、控火室、觀察室),廚房有個鍋煮著米飯(鍋上有張紙寫著“已熟”或者“未熟”),A在控火室負責關火(當看到鍋上的紙寫著“已熟”時關火),B在觀察室負責觀察米的狀態并修改鍋上貼紙的狀態字(已熟/未熟);A和B不在一個房間,無法直接交流;B隔一會觀察下鍋里的米,如果米熟了就在一張紙上寫“已熟”,未熟就寫“未熟”,B很忙,寫完字后將紙貼在了自己門上,未貼在廚房的鍋上。最終結果是,A看到鍋上的狀態字一直是“未熟”,所以不關火,最終米飯糊了。這就是可見性問題。
從內存模型理解可見性問題:juejin.im/post/684490…
3.3 解決原子性問題和內存可見性的核心
要編寫線程安全的代碼,其核心在于要對狀態(變量)訪問操作進行管理,特別是對共享的和可變的狀態的訪問。
共享意味著可由多個線程訪問操作,可變意味著可以被修改。
上述例1中,如果鹽罐不共享即其他人不能使用,則不會有線程安全性問題。如果規定不能往鹽罐中裝入,只能從鹽罐中取出,那么不管多少個人可以操作鹽罐,鹽罐中始終是鹽,沒有線程安全性問題;同樣,如果一個變量不能被修改,那么不管多少個線程操作這個變量,也不會帶來線程安全性問題。
上述例2中,如果強制B在修改狀態字后,將紙貼在鍋上,那么就可以讓A看到米飯的真正狀態,就可以及時關掉火,蒸出香噴噴的米飯。
那么,為了解決原子性問題和內存可見性問題,怎么對共享的且可變的變量進行管理?
除非需要某個域是可變的,否則應將其聲明為final域(即聲明為不可變的)
將對共享變量的并行操作轉換為串行操作(如同步機制、將變量委托給同步容器進行管理)
將共享變量轉換為不共享變量(如線程封閉(棧封閉、ThreadLocal類等))
如果某個操作需要以原子方式執行,那么就想辦法保證這個操作是原子方式執行(如給操作加鎖)
對于需要保證內存可見性的變量,可以強制線程從主內存而不是緩存中讀取變量,在線程存儲變量時強制存取到主內存中。(如加鎖,聲明volatile變量)
切記,核心是管理共享的可變狀態,鎖(內置鎖、Lock鎖)、同步容器類(Vector、Hashtable等)、并發容器類(ConcurrentHashMap、CopyOnWriteArrayList)、同步工具類(閉鎖、信號量、柵欄)、線程池等都只是是管理共享的可變狀態的工具。
總結
以上是生活随笔為你收集整理的java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 主从二进制日志_Mysql-
- 下一篇: abnf java实现_详细讲解如何利用