Java并發(十七)----變量的線程安全分析

1、成員變量和靜態變量是否線程安全
  • 如果它們沒有共享,則線程安全

  • 如果它們被共享了,根據它們的狀態是否能夠改變,又分兩種情況

    • 如果只有讀操作,則線程安全

    • 如果有讀寫操作,則這段代碼是臨界區,需要考慮線程安全

2、局部變量是否線程安全
  • 局部變量是線程安全的

  • 但局部變量引用的對象則未必

    • 如果該對象沒有逃離方法的作用訪問,它是線程安全的

    • 如果該對象逃離方法的作用范圍,需要考慮線程安全

3、局部變量線程安全分析
public static void test1() {int i = 10;i++;
}

每個線程調用 test1() 方法時局部變量 i,會在每個線程的棧幀內存中被創建多份,因此不存在共享

public static void test1();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=1, args_size=00: bipush ? ? ? ?102: istore_03: iinc ? ? ? ? ?0, 16: returnLineNumberTable:line 10: 0line 11: 3line 12: 6LocalVariableTable:Start ?Length ?Slot ?Name ? Signature3 ? ? ? 4 ? ? 0 ? ? i ? I

如圖

局部變量的引用稍有不同,先看一個成員變量的例子

class ThreadUnsafe {ArrayList<String> list = new ArrayList<>();public void method1(int loopNumber) {for (int i = 0; i < loopNumber; i++) {// { 臨界區, 會產生競態條件method2();method3();// } 臨界區}}
?private void method2() {list.add("1"); ?// 訪問的同一個成員變量list}
?private void method3() {list.remove(0);// 訪問的同一個成員變量list}
}

執行

static final int THREAD_NUMBER = 2;
static final int LOOP_NUMBER = 200;
public static void main(String[] args) {ThreadUnsafe test = new ThreadUnsafe();for (int i = 0; i < THREAD_NUMBER; i++) {new Thread(() -> {test.method1(LOOP_NUMBER);}, "Thread" + i).start();}
}

多運行幾次就會發現,其中一種情況是,如果線程2 還未 add,線程1 remove 就會報錯:

Exception in thread "Thread1" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0at java.util.ArrayList.rangeCheck(ArrayList.java:657)at java.util.ArrayList.remove(ArrayList.java:496)at cn.itcast.n6.ThreadUnsafe.method3(TestThreadSafe.java:35)at cn.itcast.n6.ThreadUnsafe.method1(TestThreadSafe.java:26)at cn.itcast.n6.TestThreadSafe.lambda$main$0(TestThreadSafe.java:14)at java.lang.Thread.run(Thread.java:748)

分析:

  • 無論哪個線程中的 method2 引用的都是同一個對象中的 list 成員變量

  • method3 與 method2 分析相同

將 list 修改為局部變量

class ThreadSafe {public final void method1(int loopNumber) {ArrayList<String> list = new ArrayList<>();for (int i = 0; i < loopNumber; i++) {method2(list);method3(list);}}
?private void method2(ArrayList<String> list) {list.add("1");}
?private void method3(ArrayList<String> list) {list.remove(0);}
}

那么就不會有上述問題了

分析:

  • list 是局部變量,每個線程調用時會創建其不同實例,沒有共享

  • 而 method2 的參數是從 method1 中傳遞過來的,與 method1 中引用同一個對象

  • method3 的參數分析與 method2 相同

方法訪問修飾符帶來的思考?

如果把 method2 和 method3 的方法修改為 public 會不會帶來線程安全問題?

  • 情況1:有其它線程調用 method2 和 method3

  • 情況2:在 情況1 的基礎上,為 ThreadSafe 類添加子類,子類覆蓋 method2 或 method3 方法,即

class ThreadSafe {public final void method1(int loopNumber) {ArrayList<String> list = new ArrayList<>();for (int i = 0; i < loopNumber; i++) {method2(list);method3(list);}}
?private void method2(ArrayList<String> list) {list.add("1");}
?private void method3(ArrayList<String> list) {list.remove(0);}
}
?
class ThreadSafeSubClass extends ThreadSafe{@Overridepublic void method3(ArrayList<String> list) {new Thread(() -> {list.remove(0);}).start();}
}

這樣的話就會存在線程安全的問題。因為method3新開了一個線程,造成多個線程訪問同一個共享資源,就會存在線程安全的問題。

從這個例子就可以看出 private 或 final 提供【安全】的意義所在。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/212283.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/212283.shtml
英文地址,請注明出處:http://en.pswp.cn/news/212283.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入了解Python pydash庫

更多資料獲取 &#x1f4da; 個人網站&#xff1a;ipengtao.com 在數據處理和分析領域&#xff0c;Python一直是一種強大的編程語言。然而&#xff0c;在處理大規模數據集和執行復雜操作時&#xff0c;有時候需要更高效的工具。在本文中&#xff0c;我們將深入探討pydash庫&am…

語義分割 簡介及數據集簡介

參考文章 MS COCO數據集介紹以及pycocotools簡單使用-CSDN博客

[MySQL--進階篇]存儲引擎的體系結構、簡介、特點、選擇

前言 ?Hello!這里是歐_aita的博客。 ?今日語錄&#xff1a;不要在乎別人怎么看你&#xff0c;因為他們根本就沒有時間&#xff0c;他們只關心他們自己。 ?個人主頁&#xff1a;歐_aita ψ(._. )>?個人專欄&#xff1a; 數據結構與算法 MySQL數據庫 存儲引擎 前言MySQL體…

代碼隨想錄算法訓練營第四十一天|343. 整數拆分、96.不同的二叉搜索樹

代碼隨想錄算法訓練營第四十一天|343. 整數拆分、96.不同的二叉搜索樹 整數拆分 343. 整數拆分 文章講解&#xff1a;https://programmercarl.com/0343.%E6%95%B4%E6%95%B0%E6%8B%86%E5%88%86.html 題目鏈接&#xff1a;https://leetcode.cn/problems/integer-break/ 視頻講解…

李宏毅gpt個人記錄

參考&#xff1a; 李宏毅機器學習--self-supervised&#xff1a;BERT、GPT、Auto-encoder-CSDN博客 用無標注資料的任務訓練完模型以后&#xff0c;它本身沒有什么用&#xff0c;GPT 1只能夠把一句話補完&#xff0c;可以把 Self-Supervised Learning 的 Model做微微的調整&am…

32.768KHz時鐘RTC晶振精度PPM值及頻差計算

一個數字電路就像一所城市的交通&#xff0c;晶振的作用就是十字路口的信號燈&#xff0c;因此晶振的品質及其電路應用尤其關鍵。數字電路又像生命體&#xff0c;它的運行就像人身體里的血液流通&#xff0c;它不是由單一的某個器件或器件單元構成&#xff0c;而是由多個器件及…

【Spring Boot 源碼學習】ApplicationListener 詳解

Spring Boot 源碼學習系列 ApplicationListener 詳解 引言往期內容主要內容1. 初識 ApplicationListener2. 加載 ApplicationListener3. 響應應用程序事件 總結 引言 書接前文《初識 SpringApplication》&#xff0c;我們從 Spring Boot 的啟動類 SpringApplication 上入手&am…

如何查詢川菜食材配料的API接口

在當今的美食文化中&#xff0c;菜譜不只是一張簡單的食譜&#xff0c;更是了解美食文化和飲食知識的重要途徑。然而&#xff0c;若沒有準確的食材配料&#xff0c;烹制出的每道菜品都將難以達到完美的味道。因此&#xff0c;為了更好地滿足人們對于菜譜和食譜的需求&#xff0…

C語言習題集(026)

//寫一個函數&#xff0c;輸入一個4位數字&#xff0c;要求輸出這4個 //數字字符&#xff0c;但每兩個數字間空一個空格。如輸入 //1990&#xff0c;應輸出"1 9 9 0"。 /* */ //解答&#xff1a; #include<stdio.h> void change(int a) { if(a/10!0) { chang…

linux權限管理以及shell

1.shell 1.1什么是shell? shell即外殼&#xff0c;是運行在linux系統上的一個腳本語言&#xff0c;包裹在linux內核的外面。我們常說的linux操作系統實際上是linux內核。我們使用的所有指令都是一個個程序&#xff0c;而shell指令就是一個將我們用戶的操作翻譯給linux內核的程…

軟件設計之組合模式

組合模式&#xff1a;將對象組合成樹形結構。 案例&#xff1a;公司管理。一個公司可以分總公司和分公司&#xff0c;無論是總公司還是分公司都有自己的部門&#xff0c;如人力資源管理部門、財務部門。分公司可以建立自己在不同地域的辦事處。請使用組合模式打印出某個公司的…

SpringSecurity6 | 登陸后的跳轉

SpringSecurity6 | 自定義認證規則 ?作者簡介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;熱愛Java后端開發者&#xff0c;一個想要與大家共同進步的男人&#x1f609;&#x1f609; &#x1f34e;個人主頁&#xff1a;Leo的博客 &#x1f49e;當前專欄&#xff1a; Ja…

第九天:信息打點-CDN繞過篇amp;漏洞回鏈amp;接口探針amp;全網掃描amp;反向郵件

信息打點-CDN繞過篇 cdn繞過文章&#xff1a;https://www.cnblogs.com/qiudabai/p/9763739.html 一、CDN-知識點 1、常見訪問過程 1、沒有CDN情況下傳統訪問&#xff1a;用戶訪問域名-解析服務器IP–>訪問目標主機 2.普通CDN&#xff1a;用戶訪問域名–>CDN節點–>…

面向LLM的App架構——業務維度

這是兩篇面向LLM的大前端架構的第一篇&#xff0c;主要寫我對LLM業務的認知以及由此推演出的大前端架構。由于我是客戶端出身&#xff0c;所以主要以客戶端角度來描述&#xff0c;并不影響對前端的適用性。 對LLM的認知 基于Google對AGI的論文&#xff0c;AGI或者LLM一定會朝…

淺談ClickHouse性能監控與調優

ClickHouse性能監控與調優 ClickHouse是一個高性能的列式數據庫管理系統&#xff0c;適用于實時分析和大數據處理。本文將詳細講解如何監控ClickHouse的性能指標、日志和查詢統計信息&#xff0c;以及如何進行故障排查和性能調優。 一、監控性能指標 1. 系統表 ClickHouse提…

網絡層重點協議——IP協議詳解

??????今天給大家分享的是網絡層的重點協議——IP協議。 清風的CSDN博客 &#x1f6e9;?&#x1f6e9;?&#x1f6e9;?希望我的文章能對你有所幫助&#xff0c;有不足的地方還請各位看官多多指教&#xff0c;大家一起學習交流&#xff01; ??????動動你們發財的…

阿里內部教程Jmeter 性能測試常用圖表、服務器資源監控

性能測試常用圖表 插件安裝 步驟 1&#xff1a;安裝插件管理器 在 Jmeter 官網上下載插件管理器 Plugins-manager-1.3.jar將 jar 包放入到 lib\ext 目錄下重啟 Jmeter&#xff0c;可以在選項下看到 Plugins Manager 選項 步驟 2&#xff1a;安裝指定的插件 打開 Plugins Ma…

JVM虛擬機系統性學習-運行時數據區(堆)

運行時數據區 JVM 由三部分組成&#xff1a;類加載系統、運行時數據區、執行引擎 下邊講一下運行時數據區中的構成 根據線程的使用情況分為兩類&#xff1a; 線程獨享&#xff08;此區域不需要垃圾回收&#xff09; 虛擬機棧、本地方法棧、程序計數器 線程共享&#xff08;數…

【矩陣】73. 矩陣置零

題目 法1&#xff1a;自己想的笨蛋方法 class Solution {public void setZeroes(int[][] matrix) {Set<Integer> rowSet new HashSet<>();Set<Integer> columnSet new HashSet<>();for (int i 0; i < matrix.length; i) {for (int j 0; j <…

DataGrip常見問題

查詢語句結果沒有輸出在output中 進行如下配置 配置后查詢結果輸出在output中 左側數據庫鏈接信息導航欄被隱藏 以上導航欄被隱藏&#xff0c;按下圖操作調出