詳情描述
在Java學習過程中總會遇到的是線程問題,Java學習線程安全問題其實就是并發(fā)的正確性問題,一個線程安全的行為,既不需要額外的同步和協調,也不用考慮在runtime中的調度和交替執(zhí)行,一定能返回預期的結果。
五種線程安全場景
1.不變性
較簡單較純粹的場景就是不變性,一個不可變的對象一定是線程安全的,如final。
2.線程安全
線程安全是不切實際的,即使是線程安全的Vector容器,也只是在方法中用了修飾,方法調用時還是需要額外同步,否則,在多線程同時remove,仍然會有Index邊界溢出的錯誤。
3.相對線程安全
一般意義上的線程安全就是相對線程安全,單獨操作是線程安全的,但是在特定情況下,還需要在調用時增加額外的同步手段。Java提供的線程安全如Vector、HashTabe、Collections.synchronizedCollection()等,都是相對線程安全。
4.線程兼容
一般意義上的不是線程安全其實是線程兼容,指的是本身并不線程安全,可以在調用時增加同步手段,實現線程安全,常見的和HashMap都是線程安全的。
5.線程對立
一些極端情況下,無論采用什么同步措施,都不能實現線程安全,就是線程對立,如Thread的suspend和resume,不能并行調用,很容易出現死鎖。
實現線程安全,既與代碼的編寫有關,也與虛擬機的同步和鎖有關,常見的三種線程安全實現方法為:
1.互斥同步
就是共享數據在并行運算中,同一時刻只能一個線程使用和都是互斥同步。
2.非阻塞同步
其實就是互斥同步的對立面,非阻塞同步相對樂觀,認為并行不一定導致共享數據沖突,如果真的出現爭用沖突,再做補償即可(如重試操作,比如compareAndSet(current,next)就是不斷嘗試賦值,如果current和next的值和預期不一致,就說明數據被修改了,會再次循環(huán)嘗試),sum.misc.Unsafe類就是非阻塞同步機制才能直接使用,用戶只能通過Java API間接使用,如非阻塞同步依賴于硬件指令集的發(fā)展和支持。
3.無同步方案
無同步方案不是不管線程安全,而是通過其他方式實現線程安全,不需要同步。
可重入代碼
一個方向是通過代碼實現無同步,就是可重入代碼,可重入代碼在執(zhí)行過程中,隨時可以中斷,轉而執(zhí)行其他任務(包括遞歸該代碼本身),然后重入繼續(xù)執(zhí)行,不會出現錯誤。
可重入代碼也叫純代碼,容易令人想起純函數(當然,不是同一維度),只要輸入相同的數據,就能返回相同的結果。
線程本地存儲
另一個方向是通過避免多線程的數據共享實現無同步,就是線程本地存儲,也就是把共享數據控制在一個線程內,避免沖突。
大部分使用消費隊列的模式都是線程本地存儲,這種模式會盡量在一個線程內完成消費,Android中的Handler機制,就是通過對象(實際上是一個為對象的hashcode,value為對象本身),讓handler引用線程的Looper,Looper再依次處理自己中的Message,通過Message的target指向handler,實現在同一線程內處理消息隊列。
千鋒教育:
千鋒西安校區(qū):
西安校區(qū)地址:西安市雁塔區(qū)高新六路52號立人科技C座西區(qū)4樓
面授課程:全棧WEB+培訓、全鏈路設計培訓、PHP全棧+服務器集群培訓、JavaEE+分布式開發(fā)培訓、大數據+人工智能培訓、 Unity游戲開發(fā)培訓、Python培訓、云計算+Python運維培訓、全棧軟件測試培訓、Android培訓、iOS培訓