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