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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发编程-12线程安全策略之常见的线程不安全类

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-12线程安全策略之常见的线程不安全类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 腦圖
  • 概述
  • 字符串拼接子之StringBuilder、StringBuffer
    • StringBuilder (線程不安全)
    • StringBuffer (線程安全)
    • 小結
  • 時間相關的類 SimpleDateFormat、第三方庫joda-time、JDK8提供的類
    • SimpleDateFormat (線程不安全的寫法)
    • SimpleDateFormat (線程安全的寫法-堆棧封閉)
    • joda-time (線程安全)
    • JDK8的時間處理類(線程安全)
  • Collections 中線程不安全的類
    • ArrayList (線程不安全)
    • HashSet (線程不安全)
  • HashMap (線程不安全)
  • 注意事項 (先檢查后執行-- 線程不安全)
  • 代碼

腦圖


概述

前兩篇博客,我們說了 通過 不可變變量 和 線程封閉 這兩種方式來實現線程安全。

這里我們來介紹下很常見的線程不安全的類

所謂線程不安全的類,是指一個類的實例對象可以同時被多個線程訪問,如果不做同步或線程安全的處理,就會表現出線程不安全的行為,比如邏輯處理錯誤、拋出異常等。


字符串拼接子之StringBuilder、StringBuffer

  • StringBuilder 一個可變的字符序列。它繼承于AbstractStringBuilder,實現了CharSequence接口。
  • StringBuffer 也是繼承于AbstractStringBuilder的子類;
  • StringBuilder和StringBuffer不同,前者是非線程安全的,后者是線程安全的。

StringBuilder (線程不安全)

運行結果

結果不等于5000,在多線程情況下,StringBuild是線程不安全的.


StringBuffer (線程安全)

運行結果

結果等于5000,在多線程情況下,StringBuffer是線程安全的.


小結

既然StringBuffer是線程安全的, 那為何JDK還要提供StringBuilder呢?

StringBuffer之所以是線程安全的原因是幾乎所有的方法都加了synchronized關鍵字,所以是線程安全的。 synchronized 同一時間只能有一個線程訪問,所以性能會相對較差。

在上篇博文 并發編程-11線程安全策略之線程封閉中,我們了解到 線程封閉可以確保線程安全,其中線程封閉的一種實現方式時堆棧封閉,說白了就是局部變量

所以推薦在堆棧封閉等線程安全的環境下(方法中的局部變量)應該首先選用StringBuilder。


時間相關的類 SimpleDateFormat、第三方庫joda-time、JDK8提供的類

SimpleDateFormat 的實例對象在多線程共享使用的時候會拋出轉換異常,正確的使用方法應該是采用堆棧封閉,將其作為方法內的局部變量而不是全局變量,在每次調用方法的時候才去創建一個SimpleDateFormat實例對象,這樣利用堆棧封閉就不會出現并發問題

另一種方式是使用第三方庫joda-time的DateTimeFormatter類 或者JDK8新提供的類 : 不可變類且線程安全 LocalDate 、java.time.LocalTime 和LocaldateTime 新的Date和Time類DateTimeFormatter


SimpleDateFormat (線程不安全的寫法)


執行結果:表現出了異常


SimpleDateFormat (線程安全的寫法-堆棧封閉)

沒有拋出異常


線程安全,無異常


joda-time (線程安全)


線程安全,無異常


JDK8的時間處理類(線程安全)


線程安全,無異常


Collections 中線程不安全的類

通常情況下,我們都是在方法內部作為局部變量使用這些集合類,很少會觸發線程不安全的問題。

如果在某些情況下定義成static,而且多個線程可以修改的時候就容易出現多線程不安全的問題。


ArrayList (線程不安全)

計數錯誤,線程不安全


HashSet (線程不安全)

計數錯誤,線程不安全


HashMap (線程不安全)

計數錯誤,線程不安全


注意事項 (先檢查后執行-- 線程不安全)

有一種寫法需要注意,即便是線程安全的對象,在這種寫法下也可能會出現線程不安全的行為,這種寫法就是先檢查后執行

if(condition(a)){handle(a); }

在這個操作里,可能會有兩個線程同時通過if的判斷,然后去執行了處理方法,那么就會出現兩個線程同時操作一個對象,從而出現線程不安全的行為。這種寫法導致線程不安全的主要原因是因為這里分成了兩步操作,這個過程是非原子性的,所以就會出現線程不安全的問題。


代碼

https://github.com/yangshangwei/ConcurrencyMaster

總結

以上是生活随笔為你收集整理的并发编程-12线程安全策略之常见的线程不安全类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。