文章編號:11434時間:2024-09-30人氣:
線程的同步是Java多線程編程的難點,往往開發者搞不清楚什么是競爭資源、什么時候需要考慮同步,怎么同步等等問題,當然,這些問題沒有很明確的答案,但有些原則問題需要考慮,是否有競爭資源被同時改動的問題?對于同步,在具體的Java代碼中需要完成以下兩個操作:把競爭訪問的資源標識為private;同步哪些修改變量的代碼,使用synchronized關鍵字同步方法或代碼。
當然這不是唯一控制并發安全的途徑。
synchronized關鍵字使用說明synchronized只能標記非抽象的方法,不能標識成員變量。
為了演示同步方法的使用,構建了一個信用卡賬戶,起初信用額為100w,然后模擬透支、存款等多個操作。
顯然銀行賬戶User對象是個競爭資源,而多個并發操作的是賬戶方法oper(int x),當然應該在此方法上加上同步,并將賬戶的余額設為私有變量,禁止直接訪問。
工作原理線程是進程中的實體,一個進程可以擁有多個線程,一個線程必須有一個父進程。
線程不擁有系統資源,只有運行必須的一些數據結構;它與父進程的其它線程共享該進程所擁有的全部資源。
線程可以創建和撤消線程,從而實現程序的并發執行。
一般,線程具有就緒、阻塞和運行三種基本狀態。
在多中央處理器的系統里,不同線程可以同時在不同的中央處理器上運行,甚至當它們屬于同一個進程時也是如此。
大多數支持多處理器的操作系統都提供編程接口來讓進程可以控制自己的線程與各處理器之間的關聯度(affinity)。
有時候,線程也稱作輕量級進程。
就象進程一樣,線程在程序中是獨立的、并發的執行路徑,每個線程有它自己的堆棧、自己的程序計數器和自己的局部變量。
但是,與分隔的進程相比,進程中的線程之間的隔離程度要小。
它們共享內存、文件句柄和其它每個進程應有的狀態。
進程可以支持多個線程,它們看似同時執行,但互相之間并不同步。
一個進程中的多個線程共享相同的內存地址空間,這就意味著它們可以訪問相同的變量和對象,而且它們從同一堆中分配對象。
盡管這讓線程之間共享信息變得更容易,但您必須小心,確保它們不會妨礙同一進程里的其它線程。
Java 線程工具和 API看似簡單。
但是,編寫有效使用線程的復雜程序并不十分容易。
因為有多個線程共存在相同的內存空間中并共享相同的變量,所以您必須小心,確保您的線程不會互相干擾。
線程屬性為了正確有效地使用線程,必須理解線程的各個方面并了解Java 實時系統。
必須知道如何提供線程體、線程的生命周期、實時系統如 何調度線程、線程組、什么是幽靈線程(Demo nThread)。
線程體所有的操作都發生在線程體中,在Java中線程體是從Thread類繼承的run()方法,或實現Runnable接口的類中的run()方法。
當線程產生并初始化后,實時系統調用它的run()方法。
run()方法內的代碼實現所產生線程的行為,它是線程的主要部分。
線程狀態附圖表示了線程在它的生命周期內的任何時刻所能處的狀態以及引起狀態改變的方法。
這圖并不是完整的有限狀態圖,但基本概括了線程中比較感興趣和普遍的方面。
以下討論有關線程生命周期以此為據。
●新線程態(New Thread)產生一個Thread對象就生成一個新線程。
當線程處于新線程狀態時,僅僅是一個空線程對象,它還沒有分配到系統資源。
因此只能啟動或終止它。
任何其他操作都會引發異常。
例如,一個線程調用了new方法之后,并在調用start方法之前的處于新線程狀態,可以調用start和sTOP方法。
●可運行態(Runnable)start()方法產生運行線程所必須的資源,調度線程執行,并且調用線程的run()方法。
在這時線程處于可運行態。
該狀態不稱為運行態是因為這時的線程并不總是一直占用處理機。
特別是對于只有一個處理機的PC而言,任何時刻只能有一個處于可運行態的線程占用處理 機。
Java通過調度來實現多線程對處理機的共享。
注意,如果線程處于Runnable狀態,它也有可能不在運行,這是因為還有優先級和調度問題。
●阻塞/非運行態(Not Runnable)當以下事件發生時,線程進入非運行態。
①suspend()方法被調用;②sleep()方法被調用;③線程使用wait()來等待條件變量;④線程處于I/O請求的等待。
●死亡態(Dead)當run()方法返回,或別的線程調用stop()方法,線程進入死亡態。
通常Applet使用它的stop()方法來終止它產生的所有線程。
線程的本操作:派生:線程在進程內派生出來,它即可由進程派生,也可由線程派生。
阻塞(Block):如果一個線程在執行過程中需要等待某個事件發生,則被阻塞。
激活(unblock):如果阻塞線程的事件發生,則該線程被激活并進入就緒隊列。
調度(schedule):選擇一個就緒線程進入執行狀態。
結束(Finish):如果一個線程執行結束,它的寄存器上下文以及堆棧內容等將被釋放。
圖2 線程的狀態與操作線程的另一個執行特性是同步。
線程中所使用的同步控制機制與進程中所使用的同步控制機制相同。
線程優先級雖然我們說線程是并發運行的。
然而事實常常并非如此。
正如前面談到的,當系統中只有一個CPU時,以某種順序在單CPU情況下執行多線程被稱為調度(scheduling)。
Java采用的是一種簡單、固定的調度法,即固定優先級調度。
這種算法是根據處于可運行態線程的相對優先級來實行調度。
當線程產生時,它繼承原線程的優先級。
在需要時可對優先級進行修改。
在任何時刻,如果有多條線程等待運行,系統選擇優先級最高的可運行線程運行。
只有當它停止、自動放棄、或由于某種原因成為非運行態低優先級的線程才能運行。
如果兩個線程具有相同的優先級,它們將被交替地運行。
Java實時系統的線程調度算法還是強制性的,在任何時刻,如果一個比其他線程優先級都高的線程的狀態變為可運行態,實時系統將選擇該線程來運行。
一個應用程序可以通過使用線程中的方法setPriority(int),來設置線程的優先級大小。
有線程進入了就緒狀態,需要有線程調度程序來決定何時執行,根據優先級來調度。
線程中的join()可以用來邀請其他線程先執行(示例代碼如下);publicclassJoin01implementsRunnable{publicstaticvoidmain(String[]args){for(inti=0;i<20;i++){if(i==5){Join01j=newJoin01();Threadt=newThread(j);(被邀請先執行的線程.);();try{//邀請這個線程,先執行();}catch(InterruptedExceptione){();}}(沒被邀請的線程。
+(i+1));}}publicvoidrun(){for(inti=0;i<10;i++){(()()+(i+1));}}}yield()告訴系統把自己的CPU時間讓掉,讓其他線程或者自己運行,示例代碼如下;publicclassYield01{publicstaticvoidmain(String[]args){YieldFirstyf=newYieldFirst();YieldSecondys=newYieldSecond();YieldThirdyt=newYieldThird();();();();}}classYieldFirstextendsThread{@Overridepublicvoidrun(){for(inti=0;i<10;i++){(第一個線程第+(i+1)+次運行.);//讓當前線程暫停yield();}}}classYieldSecondextendsThread{@Overridepublicvoidrun(){for(inti=0;i<10;i++){(第二個線程第+(i+1)+次運行.);//讓當前線程暫停yield();code原語,是JVM依賴操作系統互斥(mutex)來實現的。
而互斥是一種會導致線程掛起,并在較短的時間內又需要重新調度回原線程的,較為消耗資源的操作。
所以需要進行對線程進行優化,提高效率。
輕量級鎖輕量級鎖(Lightweight Locking)是從Java6開始引入的概念,本意是為了減少多線程進入互斥的幾率,并不是要替代互斥。
它利用了CPU原語Compare-And-Swap(CAS,匯編指令CMPXCHG),嘗試在進入互斥前,進行補救。
下面將詳細介紹JVM如何利用CAS,實現輕量級鎖。
Java Object Model中定義,Object Header是一個2字(1 word = 4 byte)長度的存儲區域。
第一個字長度的區域用來標記同步,GC以及hash code等,官方稱之為 mark word。
第二個字長度的區域是指向到對象的Class。
在2個word中,mark word是輕量級鎖實現的關鍵,其結構見右表。
從表中可以看到,state為lightweight locked的那行即為輕量級鎖標記。
bitfieds名為指向lock record的指針,這里的lock record,其實是一塊分配在線程堆棧上的空間區域。
用于CAS前,拷貝object上的mark word。
第三項是重量級鎖標記。
后面的狀態單詞很有趣,inflated,譯為膨脹,在這里意思其實是鎖已升級到OS-level。
一般我們只關注第二和第三項即可。
lock,unlock與mark word之間的聯系如右圖所示。
在圖中,提到了拷貝object mark word,由于脫離了原始mark word,官方將它冠以displaced前綴,即displaced mark word(置換標記字)。
這個displaced mark word是整個輕量級鎖實現的關鍵,在CAS中的compare就需要用它作為條件。
在拷貝完object mark word之后,JVM做了一步交換指針的操作,即流程中第一個橙色矩形框內容所述。
將object mark word里的輕量級鎖指針指向lock record所在的stack指針,作用是讓其他線程知道,該object monitor已被占用。
lock record里的owner指針指向object mark word的作用是為了在接下里的運行過程中,識別哪個對象被鎖住了。
最后一步unlock中,我們發現,JVM同樣使用了CAS來驗證object mark word在持有鎖到釋放鎖之間,有無被其他線程訪問。
如果其他線程在持有鎖這段時間里,嘗試獲取過鎖,則可能自身被掛起,而mark word的重量級鎖指針也會被相應修改。
此時,unlock后就需要喚醒被掛起的線程。
偏向鎖Java偏向鎖(Biased Locking)是Java 6引入的一項多線程優化。
它通過消除資源無競爭情況下的同步原語,進一步提高了程序的運行性能。
它與輕量級鎖的區別在于,輕量級鎖是通過CAS來避免進入開銷較大的互斥操作,而偏向鎖是在無競爭場景下完全消除同步,連CAS也不執行(CAS本身仍舊是一種操作系統同步原語,始終要在JVM與OS之間來回,有一定的開銷)。
所謂的無競爭場景,就是單線程訪問帶同步的資源或方法。
偏向鎖,顧名思義,它會偏向于第一個訪問鎖的線程,如果在接下來的運行過程中,該鎖沒有被其他的線程訪問,則持有偏向鎖的線程將永遠不需要觸發同步。
如果在運行過程中,遇到了其他線程搶占鎖,則持有偏向鎖的線程會被掛起,JVM會嘗試消除它身上的偏向鎖,將鎖恢復到標準的輕量級鎖。
(偏向鎖只能在單線程下起作用)。
偏向模式和非偏向模式,在mark word表中,主要體現在thread ID字段是否為空。
掛起持有偏向鎖的線程,這步操作類似GC的pause,但不同之處是,它只掛起持有偏向鎖的線程(非當前線程)。
在搶占模式的橙色區域說明中有提到,指向當前堆棧中最近的一個lock record(在輕量級鎖中,lock record是進入鎖前會在stack上創建的一份內存空間)。
這里提到的最近的一個lock record,其實就是當前鎖所在的stack frame上分配的lock record。
整個步驟是從偏向鎖恢復到輕量級鎖的過程。
偏向鎖也會帶來額外開銷。
在JDK6中,偏向鎖是默認啟用的。
它提高了單線程訪問同步資源的性能。
但試想一下,如果你的同步資源或代碼一直都是多線程訪問的,那么消除偏向鎖這一步驟對你來說就是多余的。
事實上,消除偏向鎖的開銷還是蠻大的。
所以在你非常熟悉自己的代碼前提下,大可禁用偏向鎖 -XX:-UseBiasedLocking。
分類線程有兩個基本類型:用戶級線程:管理過程全部由用戶程序完成,操作系統內核心只對進程進行管理。
系統級線程(核心級線程):由操作系統內核進行管理。
操作系統內核給應用程序提供相應的系統調用和應用程序接口API,以使用戶程序可以創建、執行、撤消線程。
舉例UNIX International 線程UNIX International 線程的頭文件是
這個函數是主要用于調試器。 它并不打算用于線程同步。 在一個線程調用SuspendThread擁有一個同步對象,比如互斥或關鍵部分,會導致死鎖如果調用線程試圖獲取同步對象屬于一個暫停的線程。 為了避免這種情況,一個線程在一個應用程序,它不是一個調試器應該信號其他線程暫停本身
內容聲明:
1、本站收錄的內容來源于大數據收集,版權歸原網站所有!
2、本站收錄的內容若侵害到您的利益,請聯系我們進行刪除處理!
3、本站不接受違法信息,如您發現違法內容,請聯系我們進行舉報處理!
4、本文地址:http://m.sycxjdsbhs.com/article/c6de74de5b854c563809.html,復制請保留版權鏈接!
安卓應用簽名是一種加密機制,用于驗證安卓應用程序的身份和完整性,它是安卓安全生態系統中的一個關鍵部分,可防止惡意應用程序冒充合法應用程序并竊取用戶數據或設備資源,安卓應用簽名的工作原理當您開發一個安卓應用程序時,您需要為該應用程序生成一個唯一的數字簽名,這個簽名由一個公鑰和一個私鑰組成,公鑰存儲在應用程序中,私鑰由開發者安全地保管,當...。
本站公告 2024-09-29 22:17:05
引言進度條是網站和應用程序中常見的元素,用于向用戶顯示任務或過程的完成進度,默認的進度條通常顯得單調乏味,缺乏吸引力,通過自定義、樣式和動畫,我們可以解鎖進度條的潛力,使之成為更加友好和引人入勝的交互元素,自定義進度條形狀和大小進度條可以采用各種形狀和大小,傳統的水平或垂直條形最常見,但您還可以創建圓形、環形或其他自定義形狀的進度條,...。
本站公告 2024-09-27 16:28:46
這是一款DiscuzX的插件,可以將附件存儲到阿里云OSS,功能支持阿里云OSS附件存儲支持附件上傳、刪除、下載支持附件縮略圖生成支持自定義附件存儲路徑支持多附件同時上傳支持附件分片上傳支持附件斷點續傳安裝下載插件解壓插件將解壓后的文件上傳到論壇根目錄進入論壇后臺,點擊插件管理,找到阿里云OSS附件插件,點擊安裝配置插件參數配置進入論...。
互聯網資訊 2024-09-23 21:07:27
簡介C語言是一種計算機編程語言,由丹尼斯·里奇在20世紀70年代開發,它是一種通用語言,可用于各種應用程序,從操作系統到嵌入式系統,C語言以其效率和可移植性而聞名,使其成為軟件開發人員的熱門選擇,C語言基礎數據類型C語言支持各種數據類型,包括整數、浮點數、字符和字符串,每個數據類型都有其自己的大小和存儲規則,變量變量用于存儲數據,在使...。
技術教程 2024-09-23 14:57:58
在Shell腳本中,變量是存儲數據的基本單元,使用聲明來明確變量的名稱和類型,這有助于提高代碼的可讀性和可維護性,本指南將深入探討Shell中變量聲明的強大工具shelldeclare,什么是shelldeclare,shelldeclare是Bash和其他POSIX兼容Shell中的一個內置命令,用于聲明和初始化變量,它提供了對變量...。
互聯網資訊 2024-09-23 13:20:06
簡介長整型,在許多編程語言中也稱為整數,是一種用于存儲整數的數據類型,它通常用于表示比標準整型更大的值,在某些情況下,使用長整型可以顯著提高代碼效率和性能,長整型的優點與標準整型相比,長整型具有以下優點,存儲更大的值,長整型可以存儲比標準整型更大的值,使其適用于需要處理大數的應用程序,減少溢出,由于長整型可以存儲更大的值,它可以減少整...。
互聯網資訊 2024-09-23 12:33:45
文本框是網站上常見的輸入元素,它允許用戶在其中輸入文本,但有時當文本框中的內容較長或包含過多的行時,就會出現滾動條,默認情況下,文本框的滾動條樣式可能不符合您網站的設計,因此自定義滾動條的外觀有助于增強用戶體驗和網站的美觀度,自定義滾動條樣式要自定義滾動條樣式,您可以使用CSS的,webkit,scrollbar偽類選擇器,適用于...。
技術教程 2024-09-23 01:04:56
u003e以下是一個優雅下拉菜單的示例,下拉菜單選項1選項2選項3通過遵循這些技巧,您可以創建優雅且用戶友好的下拉菜單,以增強您網站的交互體驗,...。
互聯網資訊 2024-09-13 20:03:34
=document.querySelector,function,.value,letresult,switch,functionName,casearcsin,result=Math.asin,angle,break,casearccos,result=Math.acos,angle,break,casearctan,resu...。
最新資訊 2024-09-13 14:21:51
簡介Java虛擬機,JVM,是一個運行Java字節碼的計算機程序,它負責加載、驗證、執行和存儲Java類文件,JVM是Java語言的基礎,支持在各種平臺上執行Java程序,JVM的體系結構JVM由以下主要組件組成,類加載器,負責加載Java類文件并將其轉換為內部表示形式,字節碼驗證器,驗證加載的類文件是否符合Java虛擬機規范,執行引...。
最新資訊 2024-09-12 22:49:46
前言中國作為全球數字化大國,對于開發者而言是一個充滿機遇的沃土,為了助力中國開發者茁壯成長,本文匯集了豐富的資源和支持,旨在為他們的職業發展提供全方位的賦能,教育與培訓在線課程平臺網易云課堂,提供海量免費和付費課程,涵蓋從基礎編程到高級技術,Coursera,與世界名校合作,提供計算機科學、數據科學和AI等領域的認證課程,Udemy,...。
互聯網資訊 2024-09-09 10:03:16
百邦手機快修連鎖,1、口碑方面,百邦手機快修連鎖在廈門非常的出名,是一家全國連鎖店,具有非常好的口碑,2、技術方面,百邦手機快修連鎖的技術非常不錯,獲得過,修手機的一些獎項,全國知名的手機連鎖維修機構有哪些連鎖手機維修店,其實不算多出名的也就那十來家,淘配配,閃修俠,極客修,加速度,e修大師,機大師,51修,Hi維修,愛維修,馬上修,...。
技術教程 2024-09-02 04:02:24