摘要:在兩個線程訪問同一個對象中的同步方法時一定是線程安全的。當(dāng)一個線程訪問的一個同步代碼塊時,其他線程對同一個鐘所有其他同步代碼塊的訪問被阻塞,這說明使用的對象監(jiān)視器是一個。
“非線程安全”其實(shí)會在多個線程對同一個對象中的實(shí)例變量進(jìn)行并發(fā)訪問時發(fā)生,產(chǎn)生的后果就是“臟讀”,也就是取到的數(shù)據(jù)其實(shí)是被更改過的。而“線程安全”就是以獲得的實(shí)例變量的值是經(jīng)過同步處理的,不會出現(xiàn)臟讀的現(xiàn)象。
“非線程安全”問題存在于“實(shí)例變量”中,如果是方法內(nèi)部的私有變量,則不存在“非線程安全”問題,所得結(jié)果也就是“線程安全”的了。
在兩個線程訪問同一個對象中的同步方法時一定是線程安全的。
關(guān)鍵字synchronized取得的鎖都是對象鎖,而不是一段代碼或方法當(dāng)作鎖,哪個線程先執(zhí)行帶synchronized關(guān)鍵字的方法,哪個 線程就是持有該方法所屬對象的鎖Lock,那么其他線程只能呈等待狀態(tài),前提是多個線程訪問的是同一個對象。但多個線程訪問多個對象,則JVM會創(chuàng)建多個鎖。
調(diào)用關(guān)鍵字synchronized聲明的方法一定是排隊(duì)運(yùn)行的,只有共享資源的讀寫才需要同步化。
A線程先持有object對象的Lock鎖,B線程可以以異步的方式調(diào)用object對象中的非synchronized類型的方法
A線程先持有object對象的Lock鎖,B線程如果在這時調(diào)用object對象中的synchronize類型的方法則需等待,也就是同步。
發(fā)送臟讀的情況是在讀取實(shí)例變量時,此值已經(jīng)被其他線程更改過了。
關(guān)鍵字synchronized擁有鎖重入的功能,也就是在使用synchronized時,當(dāng)一個線程得到一個對象鎖后,再次請求此對象時是可以再次得到該對象的鎖的。這也證明在一個synchroized方法內(nèi)部調(diào)用本類的其他synchronized方法時,是永遠(yuǎn)可以得到鎖的。
當(dāng)存在父子類繼承關(guān)系時,子類是完全可以通過“可重入鎖”調(diào)用父類的同步方法的。
出現(xiàn)異常的鎖被自動釋放。
同步不能繼承,所以還得在子類的方法中添加synchronized關(guān)鍵字。
synchronized方法是對當(dāng)前對象進(jìn)行加鎖,而synchronized代碼塊是對某一個對象進(jìn)行加鎖。
當(dāng)兩個并發(fā)線程訪問同一個對象object中的synchronized(this)同步代碼塊時,一段時間內(nèi)只能有一個線程被執(zhí)行,另一個線程必須等待當(dāng)前線程執(zhí)行完這個代碼塊以后才能執(zhí)行該代碼塊。
不在synchronized塊中就是異步執(zhí)行,在synchronized塊中就是同步執(zhí)行。
當(dāng)一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對同一個object鐘所有其他synchronized(this)同步代碼塊的訪問被阻塞,這說明synchronized使用的“對象監(jiān)視器”是一個。
和synchronized方法一樣,synchronized(this)代碼塊也是鎖定當(dāng)前對象的。
鎖非this對象具有一定的優(yōu)點(diǎn):如果在一個類中有很多個synchronized方法,這時雖然能實(shí)現(xiàn)同步,但會受到阻塞,所以影響運(yùn)行效率;但如果使用同步代碼塊鎖非this對象,則synchronized(非this)代碼塊中的程序與同步方法是異步的,不與其他鎖this同步方法爭搶this鎖,則可以大大提高運(yùn)行效率。
多個線程調(diào)用同一個對象中的不同名稱的synchronized同步方法或synchronized(this)同步代碼塊時,調(diào)用的效果就是按順序執(zhí)行,也就是同步的,阻塞的。
同步代碼塊放在非同步synchronized方法中進(jìn)行聲明,并不能保證調(diào)用方法的線程的執(zhí)行同步/順序性,也就是線程調(diào)用方法是順序是無序的,雖然在同步代碼塊中執(zhí)行的順序是同步的,這樣極易出現(xiàn)“臟讀”問題。
synchronized(非this對象x)格式的寫法是將x對象本身作為“對象監(jiān)視器”,這樣就可以得出以下3個結(jié)果:
1)當(dāng)多個線程同時執(zhí)行synchronized(x){}同步代碼塊呈同步效果。
2)當(dāng)其他線程執(zhí)行x對象中synchronized同步方法時呈同步效果。
3)當(dāng)其他線程執(zhí)行x對象方法里面的synchroinzed(this)代碼塊時也呈同步效果。
但要注意,如果其他線程調(diào)用不加synchronized關(guān)鍵字的方法時,還是異步調(diào)用。
synchronized關(guān)鍵字加到static靜態(tài)方法上是給Class類上鎖,而synchroinzed關(guān)鍵字加到非static靜態(tài)方法上是給對象上鎖。
異步的原因是持有不同的鎖,一個是對象鎖,另外一個是Class鎖,而Class鎖可以對類的所有對象實(shí)例起作用。
當(dāng)string的多個值都是相同時候(aa),兩個線程持有相同的鎖,所以造成線程B不能執(zhí)行。這就是String 常量池所帶來的問題。因此大多數(shù)的情況下,同步synchronized代碼塊都不使用string作為鎖對象,而改用其他,比如new object()實(shí)例化一個Object對象,但它并不放入緩存中.
因?yàn)橥降木€程都在等待根本不可能被釋放的鎖,從而導(dǎo)致所有的任務(wù)都無法繼續(xù)完成,是線程死鎖。
進(jìn)入jdk的bin目錄,執(zhí)行jps命令,獲取線程run的id,再執(zhí)行jstack -l run線程id。
在內(nèi)置類中有兩個同步方法,但使用的卻是不同的鎖,打印的結(jié)果也是異步的。
同步代碼塊synchronized(class2)對class2上鎖以后,其他線程只能以同步的方式調(diào)用class2中的靜態(tài)同步方法。
如果同時持有相同的鎖對象,則這些線程之間就是同步的;如果分別獲得鎖對象,這些線程之間就是異步的。
只要對象不變,即使對象的屬性被改變,運(yùn)行的結(jié)果還是同步的。
關(guān)鍵字volatile的主要作用是變量在多個線程間可見。
關(guān)鍵字volatile的作用是強(qiáng)制從公共堆棧中取得變量的值,而不是從線程私有數(shù)據(jù)棧中取得變量的值。
volatile關(guān)鍵字最致命的缺點(diǎn)是不支持原子性。
關(guān)鍵字volatile主要使用的場合是多個線程中可以感知實(shí)例變量被更改了,并且可以獲得最新的值使用,也就是用多線程讀取共享變量可以獲得最新值使用。
read和load階段:從主存復(fù)制變量到當(dāng)前線程工作內(nèi)存;
use和assign階段:執(zhí)行代碼,改變共享變量值; store和write階段:用工作內(nèi)存數(shù)據(jù)刷新主內(nèi)存對應(yīng)變量的值;
對于用volatile修飾的變量,jvm虛擬機(jī)只是保證從主內(nèi)存加載線程工作內(nèi)存的值是最新的。
原子操作是不能分割的整體,沒有其他線程能夠中斷或檢查正常原子操作中的變量。
atomicInteger也不一定是安全的,雖然addAndGet()方法是原子的,但方法和方法之間的調(diào)用卻不是原子的。解決這樣的問題必須要用同步。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/68057.html
摘要:使用雙檢查機(jī)制來實(shí)現(xiàn)多線程環(huán)境中的延遲加載單例設(shè)計(jì)模式。類主要負(fù)責(zé)日期的轉(zhuǎn)換與格式化,但在多線程環(huán)境中,使用此類容易造成數(shù)據(jù)轉(zhuǎn)換及處理的不準(zhǔn)確,因?yàn)轭惒⒉皇蔷€程安全的。 立即加載就是使用類的時候已經(jīng)將對象創(chuàng)建完畢,常見的實(shí)現(xiàn)辦法就是直接new實(shí)例化。而立即加載從中文的語境來看,有著急、急迫的含義,所以也稱為餓漢模式。 package com.zxf.demo.singleton_0; ...
摘要:線程是在進(jìn)程中獨(dú)立運(yùn)行的子任務(wù)。線程中斷狀態(tài)由該方法清除。測試線程對象是否已經(jīng)是中斷狀態(tài),但不清除狀態(tài)標(biāo)志。高優(yōu)先級的線程總數(shù)大部分先執(zhí)行完,但不代表高優(yōu)先級的線程全部先執(zhí)行完。當(dāng)進(jìn)程中不存在非守護(hù)線程了,則守護(hù)線程自動銷毀。 進(jìn)程是受操作系統(tǒng)管理的基本運(yùn)行單元。 線程是在進(jìn)程中獨(dú)立運(yùn)行的子任務(wù)。使用多任務(wù)操作系統(tǒng)Windows后,可以最大限度地利用CPU的空閑時間來處理其他的任務(wù)。...
摘要:調(diào)用代碼的線程就持有了對象監(jiān)視器,其他線程只有等待鎖被釋放時再次爭搶。使用多個對象,可以喚醒部分指定線程,有助于提升程序運(yùn)行的效率。方法的作用是返回等待與此鎖定相關(guān)給定條件的線程估計(jì)數(shù)。線程在等待時間到達(dá)前,可以被其他線程提前喚醒。 調(diào)用lock.lock()代碼的線程就持有了對象監(jiān)視器,其他線程只有等待鎖被釋放時再次爭搶。效果和使用synchronized關(guān)鍵字一樣,線程之間執(zhí)行的...
摘要:使用工具監(jiān)測死鎖進(jìn)入的安裝目錄中的目錄,執(zhí)行命令可以看出得到運(yùn)行的線程的值為,再執(zhí)行命令,查看結(jié)果 死鎖 Java 線程是死鎖是一個經(jīng)典的多線程問題,因?yàn)椴煌木€程都在等待根本不可能被釋放的鎖,從而導(dǎo)致所有的任務(wù)都無法繼續(xù)完成 舉個例子 DealThread.java package dealThread.demo; public class DealThread implement...
閱讀 1391·2023-04-26 03:04
閱讀 2325·2019-08-30 15:44
閱讀 3727·2019-08-30 14:15
閱讀 3507·2019-08-27 10:56
閱讀 2703·2019-08-26 13:53
閱讀 2616·2019-08-26 13:26
閱讀 3075·2019-08-26 12:11
閱讀 3609·2019-08-23 18:21