多線程、進程、線程五種狀態、synchronized、volatile、Lock、CAS、死鎖、ThreadLocal

1、并發編程

并發編程三要素

  • 原子性:只一個操作要么全部成功,要么全部失敗
  • 可見性:一個線程對共享變量的修改,其他線程能夠立刻看到
  • 有序性:程序執行的順序按照代碼的先后順序執行

synchronized,Lock解決原子性問題
volatile,,Lock解決可見性和有序性問題

2、線程和進程的區別

  • 根本區別:進程是操作系統資源分配的最小單位;線程是處理任務調度和執行的最小單位
  • 資源開銷:每個進程都有單位的空間,進程間的切換有較大的開銷;線程是輕量級的進程,同一類線程共享數據空間,每個線程有獨立的運行棧和程序計數器,線程之間的切換開銷較小
  • 包含關系:進程包含線程
  • 內存分配:線程共享地址空間和資源,進程之間的地址空間和資源相互獨立
  • 影響關系:一個進程崩潰,在保護模式下其他進程不受影響;一個線程崩潰,其他線程也會受影響,整個進程都會崩潰。多進程要比多線程更加健壯
  • 執行關系:進程有獨立的執行入口,線程不能獨立執行,必須依賴進程

上下文切換:任務從保存到再加載的過程就是一次上下文切換。

3、創建線程的四種方式

  • 繼承Thread
  • 實現Runnable接口
  • 實現Callable接口
  • 使用Executors工具類創建線程池

Runnable和Callable區別

相同點:

  • 都是接口;
  • 都可以編寫多線程程序;
  • 都采用Thread.start()啟動線程

不同點

  • Runnable接口的run()方法沒有返回值 ;Callable()接口的call()方法有返回值,是個泛型
  • Runnable接口run()方法只能拋出運行時異常,且無法捕捉處理;Callable接口call()方法允許拋出異常,可以獲取異常信息

線程的run()和start()有何區別

  • start()用于啟動線程,run()用于執行線程運行時的代碼。run()方法可以重復調用,start()只能調用一次
  • start()方法用于啟動線程,真正實現了多線程的運行。調用start()時無需等待run()方法方法體代碼執行完畢就可以執行其他代碼;此時線程是就緒態,并沒有開始運行,然后通過Thread類調用run()方法完成其運行狀態,run()方法運行結束,此線程就終止了
  • run()方法是在線程里的,直接調用run()方法,相當于調用了一個普通的函數,必須等待run()方法執行完畢才可以執行下面的代碼,所以執行路徑還是一條,沒有多線程的特征,所以在線程啟動時,要調用start()方法而不是run()方法。

Future和FutureTask

  • Callable接口的call()方法有返回值,Future可以拿到異步執行任務(這個任務也許并沒有完成)的返回值,并且可以拋出異常信息。
  • FutureTask是Future的具體實現。FutureTask實現了RunnableFuture接口。RunnableFuture接口又同時繼承了Future和 Runnable接口。所以FutureTask既可以作為Runnable被線程執行,又可以作為Future得到Callable的返回值。

4、線程的狀態和基本操作

線程的五種狀態和生命周期

在這里插入圖片描述

  • 新建(new)
  • 可運行/就緒態(runnable):調用start()方法后就處于Runnable態
  • 運行(running):runnable態獲取到時間片,就進入running態;就緒態是進入運行態的唯一入口,線程要進入運行態就必須要進入就緒態
  • 阻塞(block)
  • 死亡(dead):死亡的線程不可復生

線程調度的方法

1、wait():使一個線程處于阻塞等待狀態,并且釋放所持有的對象鎖
2、sleep():使役個正在運行的線程處于睡眠狀態,是一個靜態方法
3、notify():喚醒一個處于等待隊列的線程,再調用此方法時,并不能確切的喚醒某個等待的線程,由JVM確定喚醒哪個線程,并且與優先級無關
4、notifyAll():喚醒所有處于等待隊列的線程,然后重新競爭鎖

wait()和sleep()區別

  • 所在類不同:sleep()是Thread類的靜態方法;wait()是Object類的方法
  • 鎖:sleep()不釋放鎖,wait()釋放鎖
  • 用途:wait()用于線程之間通信;sleep()用于暫停線程執行
  • 用法不同:wait()在結束后,不會自動蘇醒,需要別的線程調用同一個對象上的notify()或者notifyAll()去喚醒;而sleep()方法在結束后,自動蘇醒。

interrupt()、interrupted()、isInterrupted()

  • interrupt()、isInterrupted()是通過Thread對象調用,是實例方法;interrupted()是通過Thread類調用,是靜態方法
  • interrupt()方法,只是通知該線程停止運行,只是通知,并沒有直接中斷,而是由程序自己決定是否中斷

線程類的構造方法、靜態代碼塊是被new這個線程的類的線程所調用的(誰new誰調用),run()方法是自身線程調用

5、synchronized

作用:用來控制線程同步的,被synchronized修飾的代碼不能被多個線程同時執行,可以修飾類、方法、變量

synchronized底層原理

synchronized修飾的代碼在反編譯為字節碼文件時,前后都出現了monitor字樣,前面出現的是monitorenter,后面出現的是monitorexit,就是釋放鎖。當執行monitorenter時,當前線程試圖獲取對象鎖所持有的monitor,當計數器為0時,就可以成功獲取,當獲取到時,計數器+1。并且就算當前線程已經擁有對象鎖的monitor的持有權,那么就可以重入這個monitor,重入計數器也會加一。如果其他線程占有monitor持有權,那么當前線程就會阻塞,知道其他線程執行monitorexit,執行后鎖釋放,計數器設置為0。

自旋

即其他線程不進入阻塞態,而是在synchronized邊界循環等待,不斷嘗試獲取鎖,這就是自旋

synchronized鎖升級

synchronized涉及到用戶態和內核態的切換,在1.6之前,鎖都是重量級鎖,即我們不管什么線程來操作資源,都要進行加鎖釋放鎖,如果有多線程,還要等待之類的,很浪費資源,1.6之后引入了偏向鎖與輕量鎖來減小獲取和釋放鎖所帶來的性能消耗。

鎖升級其實就是對synchronized的優化,以前用synchronized修飾一個對象或者是方法,方法也等于是鎖住對象,直接用一把操作系統層面的大鎖,萬一只有少量線程的話會大題小作了,如果大量線程的話又會特別消耗時間,劃不來,所以要將以前的二話不說用一把大鎖進行優化。

無鎖->偏向鎖->輕量級鎖->重量級鎖

原理:在鎖對象的對象頭有一個threadid字段,第一次訪問時threadid為空,JVM讓其持有偏向鎖,并把threadid設置為線程id,再次進入時只需要判斷兩個id是否相等,相等就直接進入,不相等就升級為輕量級鎖;自旋一段時間后還沒有獲取到就升級到重量級鎖。

synchronized、volatile、CAS區別

  • synchronized是悲觀鎖,屬于搶占式,會引起其他線程阻塞
  • volatile提供多個線程共享變量可見性和禁止指令重排序
  • CAS是基于沖突監測的樂觀鎖(非阻塞)

synchronized、Lock、ReentrantLock區別

  • synchronized、ReentrantLock都是可重入鎖
  • synchronized是關鍵字,Lock是接口,ReentrantLock是實現了Lock接口的一個類
  • synchronized可以給類、方法、代碼塊加鎖,Lock和ReentrantLock只能給代碼塊加鎖
  • synchronized不用手動獲取和釋放,發生異常會自動釋放鎖,不會造成死鎖;Lock和ReentrantLock需要手動,沒有unLock()就會死鎖
  • Lock可以知道是否成功獲取到鎖,synchronized不行

6、volatile

保證可見性和禁止指令重排序,提供happens-before的保證,確保一個線程的修改對于其他線程是可見的。被volatile修飾的共享變量,當它被修改時,可以將修改的值立即更新到主內存中,其他線程需要讀取時,重新去主內存中讀取新值
volatile可以保證可見性和禁止重排序,但不能保證原子性;atomic方法可以讓這種方法具有原子性

7、Lock體系

Lock是synchronized的擴展版本,Lock提供了無條件的、可輪詢的(tryLock方法)、定時的(tryLock帶參方法)、可中斷的(lockInterruptibly)、可多條件隊列的鎖操作。Lock的實現基本都支持公平鎖和非公平鎖,synchronized只支持非公平鎖

  • 悲觀鎖:悲傷的假設最壞的情況,每次拿數據都認為別人會修改,所以在拿的時候就會加鎖,別人想拿就阻塞(共享資源每次只給一個線程使用,其他線程阻塞,用完再把資源轉讓給其他線程)
  • 樂觀鎖:每次拿數據,不會上鎖,直到提交數據時才會證實數據是否被修改(產生并發沖突),多用于多讀場景。一般用版本號或者CAS實現

8、CAS

CompareAndSweep——比較并交換
CAS包含三個操作數——內存位置(V)、預期值(A)、擬寫入的新值(B)

  • 第一步:比較V和A是否相等
  • 第二步:相等,就把B寫入V
  • 第三步:返回boolean類型,表示操作成功

多個線程進行CAS操作時,只有一個線程可以操作成功,其他線程自旋等待

CAS產生的問題

  • ABA問題:從A變到B,再從B變到A,過程不知道;解決辦法:引入版本號
  • 循環開銷時間大:資源競爭嚴重時,CAS自旋概率大,浪費CPU
  • 只能保證一個共享變量的原子性操作

9、線程死鎖

兩個或以上的線程互相持有對方資源并且不主動釋放造成的惡性循環

死鎖的四個條件

  • 互斥條件:一個資源只能被一個線程占用
  • 請求與保持條件:請求被占用資源而阻塞,不放棄已經獲得的資源
  • 不剝奪條件:資源未使用前不能被其他線程強行剝奪
  • 循環等待條件:等待的線程形成了一個死循環

避免死鎖

破壞造成死鎖四個條件中的一個就行

  • 互斥條件無法破壞
  • 破壞請求與保持條件:一次性申請所有資源
  • 破壞不剝奪條件:申請不到被占用的資源,就主動釋放
  • 破壞循壞等待條件:

活鎖

沒有被阻塞,只是某些條件沒滿足,導致一直重復嘗試、失敗、嘗試、失敗這個過程
活鎖有可能自己解開,死鎖不能

饑餓

因為種種原因無法獲取到所需要的資源,導致一直無法執行

10、ThreadLocal

為線程提供局部變量,保證各個線程里的變量獨立于其他線程的變量,也就是說ThreadLocal為每個線程創建一個單獨的副本,線程之間不相關,
同步機制是為了保證多線程環境下數據的統一性,而ThreadLocal則是保證多線程環境下數據的獨立性

ThreadLocal底層原理

Thread類中有一個ThreadHashMap的數據結構,用來保存線程對象的變量
每個線程的ThreadHashMap都是屬于線程自己的,這就保證了每個線程都是獨立的,多個操作不會互相影響

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

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

相關文章

前端vue 動態加載ts文件,動態調用ts內的方法

業務場景: 在某個業務場景中, 我們需要在數據庫配置ts文件路徑,和需要調用的函數名稱, 前端需要再指定的場景下,觸發對應的函數, 并執行處理邏輯,返回結果. 實現: 這是一個數據庫配置生成的動態表單 動態校驗的例子, 需要引用動態的函數校驗 任意一個js文件, common1.ts c…

大模型日報|今日必讀的 13 篇大模型論文

大家好,今日必讀的大模型論文來啦! 1.MIT新研究:并非所有語言模型特征都是線性的 最近的研究提出了線性表征假說:語言模型通過操作激活空間中概念(“特征”)的一維表征來執行計算。與此相反,來…

CHI dataless 傳輸——CHI(4)

上篇介紹了read的操作類型,本篇我們來介紹一下dataless 目錄 一、dataless操作概覽 二、Non-CMO (Non-Cache Maintenance Operation) 1、CleanUnique 2、StashOnce and StashOnceSep 3、Evict 三、CMO (Cache Maintenance Operation) 一、dataless操作概覽 名…

C# 中的 Dictionary<TKey, TValue> 類

Dictionary<TKey, TValue> 是 C# 中的一個泛型集合類,它提供了一種鍵值對的存儲結構,可以用來存儲和快速訪問數據。它的主要特點如下: 鍵值對結構: Dictionary 中的每個元素都是一個鍵值對,鍵必須是唯一的,值可以重復。 快速訪問: Dictionary 基于哈希表實現,可以提供 O…

大白話聊聊MySQL查詢之五子句(知識簡單但重要)

前言&#xff1a; 在日常開發中&#xff0c;查詢數據占很大的比重&#xff0c;在使用 MySQL 數據庫進行查詢時&#xff0c;我們經常需要通過各種條件和規則來篩選和排序數據。要實現這些功能&#xff0c;就不得不使用以下這些子句&#xff1a;WHERE、ORDER BY、GROUP BY、HAVI…

物聯網層次架構設計

物聯網可以分為三個層次&#xff0c;底層是用來感知數據的感知層&#xff0c;即利用傳感器、二維碼、RFID等設備隨時隨地獲取物體的信息。第二層是數據傳輸處理的網絡層&#xff0c;即通過各種傳感網絡與互聯網的融合&#xff0c;將對象當前的信息實時準確地傳遞出去。第三層則…

忍の摸頭之術游戲娛樂源碼

本資源提供給大家學習及參考研究借鑒美工之用&#xff0c;請勿用于商業和非法用途&#xff0c;無任何技術支持&#xff01; 忍の摸頭之術游戲娛樂源碼&#xff0c;抖音上面非常火的摸頭殺畫面,看得我眼花繚亂,源碼拿去玩吧&#xff1b; 目錄說明 忍の摸頭之術&#xff1a;域…

輕松同步:將照片從三星手機傳輸到iPad的簡便方法

概括 想要在新 iPad 上查看三星照片嗎&#xff1f;但是&#xff0c;如果您不知道如何將照片從三星手機傳輸到 iPad&#xff0c;則無法在 iPad 上查看圖片。為此&#xff0c;本文分享了 7 個有用的方法&#xff0c;以便您可以使用它們在不同操作系統之間輕松發送照片。現在&…

EfficientSAM分割對象后求其中圖像中的高

1 分割對象 EfficientSAM https://github.com/yformer/EfficientSAM 2 計算在圖像中最高點即y值最小點 import os import cv2def read_images(folder_path):image_files [f for f in os.listdir(folder_path) iff.endswith(".jpg") or f.endswith(".png&quo…

c語言之運算符練習題

C語言中的運算符是執行特定操作的符號&#xff0c;它們是編程中不可或缺的部分。C語言提供了多種類型的運算符&#xff0c;包括算術運算符、關系運算符、邏輯運算符、位運算符、賦值運算符等。以下是一些常見的C語言運算符練習題&#xff0c;可以幫助你熟悉和練習這些運算符的使…

虛擬化技術[1]之服務器虛擬化

文章目錄 虛擬化技術簡介數據中心虛擬化 服務器虛擬化服務器虛擬化層次寄居虛擬化裸機虛擬化VMM無法直接捕獲特權指令解決方案 服務器虛擬化底層實現CPU虛擬化內存虛擬化I/O設備虛擬化 虛擬機遷移虛擬機動態遷移遷移內容&#xff1a;內存遷移遷移內容&#xff1a;網絡資源遷移遷…

小短片創作-組裝場景(一)

1、項目基礎設置 通過第三人稱模板&#xff0c;創建1個項目 1.自動曝光&#xff1a;關閉&#xff0c;因為要做專業的小短片&#xff0c;曝光需要手動控制。 2.擴展自動曝光中的默認亮度范圍&#xff1a;啟用 3.全局光照系統&#xff1a;選擇屏幕空間光照&#xff08;SSGI&am…

Transformer詳解常見面試問題

文章目錄 1. 各模塊解決1.1 輸入部分1.2 多頭注意力&#xff08;作者使用8個頭&#xff09;1.3 殘差和LayerNorm1.4 Decoder部分 2.Transformer經典問題2.1 tranformer為何使用多頭注意力機制&#xff1f;2.2 Transformer相比CNN的優缺點2.3 Encoder和decoder的區別&#xff1f…

Spring中RestTemplate用法

系列文章目錄 文章目錄 系列文章目錄前言 前言 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站&#xff0c;這篇文章男女通用&#xff0c;看懂了就去分享給你的碼吧。 RestTemplate 是從…

自編譯frida得一些記錄

frida編譯 這個過程坑肯定很多 但是只要大方向對得&#xff0c;解決掉每個小錯誤達到目的就ok得 # 就是想自己把frida代碼done下來改一改 然后看看git clone gitgithub.com:frida/frida.git git fetch git checkout 14.1.3# 下載node包管理工具 apt install nvm nvm install …

Web Speech API(1)—— SpeechRecognition

Web Speech API 使你能夠將語音數據合并到 Web 應用程序中。Web Speech API 有兩個部分&#xff1a;SpeechSynthesis 語音合成&#xff08;文本到語音 TTS&#xff09;和 SpeechRecognition 語音識別&#xff08;異步語音識別&#xff09;。 SpeechRecognition 語音識別通過 S…

axios案例應用

1、Spring概述 Spring 是分層的 Java SE/EE 應用 full-stack 輕量級開源框架&#xff0c;以 IoC(Inverse Of Control: 反轉控制)和 AOP(Aspect Oriented Programming:面向切面編程)為內核&#xff0c;提供了展現層 Spring MVC 和持久層。Spring JDBC 以及業務層事務管理等眾多…

day16|二叉樹的屬性

相關題目 ● 104.二叉樹的最大深度 559.n叉樹的最大深度 ● 111.二叉樹的最小深度 ● 222.完全二叉樹的節點個數 二叉樹的深度與高度 如圖&#xff0c; 二叉樹的深度表示&#xff1a;任意一個葉子節點到根節點的距離&#xff0c;是從上往下計數的&#xff0c;因此使用前序遍歷…

2024年甘肅特崗教師招聘報名流程,速速查收哦!

2024年甘肅特崗教師招聘報名流程&#xff0c;速速查收哦&#xff01;

python-雞兔同籠問題:已知雞和兔的總頭數與總腳數。求籠中雞和兔各幾只?

【問題描述】典型的雞兔同籠問題。 【輸入形式】輸入總頭數和總腳數兩個實數&#xff1a;h&#xff0c;f 【輸出形式】籠中雞和兔的個數&#xff1a;x&#xff0c;y 【樣例輸入】16 40 【樣例輸出】雞12只&#xff0c;兔4只 【樣例說明】輸入輸出必須保證格式正確。…