
1.synchronized關(guān)鍵字
1.1什么意思
synchronized關(guān)鍵字主要是用來解決多個(gè)線程訪問資源的同步性,也就是保證被修飾的方法或者代碼塊任意時(shí)刻都只能有一個(gè)線程在執(zhí)行。
底層實(shí)現(xiàn)是在修飾的前后加上minitorenter/minitorexit:
minitorenter:當(dāng)需要獲取鎖的時(shí)候,會檢查鎖的計(jì)數(shù)器,如果是0,可以獲取;如果是1,則不能獲取
minitorexit:當(dāng)執(zhí)行完了,會把鎖的計(jì)數(shù)器設(shè)置為0.
1.2如何使用(3種方法)
1.2.1修飾實(shí)例方法:作用相當(dāng)于對當(dāng)前的實(shí)例對象加鎖
1.2.2修飾靜態(tài)方法:相當(dāng)于對當(dāng)前的類加鎖,也就是說當(dāng)前類的所有實(shí)例對象在不同的線程中,同一時(shí)間最多只能有一個(gè)線程調(diào)用該靜態(tài)方法。
1.2.3修飾代碼塊:給指定的Object加鎖,需要注意的是,最好不要用該關(guān)鍵詞修飾String,因?yàn)樵贘VM中,字符串常量詞存在緩存功能,本意是給2個(gè)線程加不同的鎖,但是放入的是String的話,2個(gè)線程持有的是相同的鎖,導(dǎo)致某一個(gè)線程無法正常運(yùn)行。
public class SynTest { public static class Threads implements Runnable{ @Override public void run() { mbClass mb0 = new mbClass(); try { // mb0.say(); // mb0.says(); mb0.sayss(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static class mbClass{ synchronized public void say() throws InterruptedException{ for(int i = 0; i<10;i++) { System.out.print(i); } System.out.println("開始等待"); Thread.sleep(3000); System.out.println("等待結(jié)束"); } synchronized public static void says() throws InterruptedException{ for(int i = 0; i<3;i++) { System.out.print("k"); } System.out.println("開始等待+"); Thread.sleep(3000); System.out.println("等待結(jié)束+"); } public void sayss() throws InterruptedException{ synchronized(mbClass.class) { System.out.println("開始+"); for(int i = 0; i<3;i++) { System.out.print("QQQ"); } Thread.sleep(3000); System.out.println("結(jié)束+"); } } } public static void main(String[] args) { // TODO Auto-generated method stub Threads p = new Threads(); new Thread(p,"線程1").start(); Threads q = new Threads(); new Thread(q,"線程2").start(); } }
這里就不放結(jié)果了,可以把注釋的2種方法,特別是say()和says()之間的區(qū)別。
1.3synchronized和Lock的區(qū)別
首先synchronized是java的關(guān)鍵字,是JVM層面實(shí)現(xiàn)的,而Lock是個(gè)接口,是JDK層面實(shí)現(xiàn)的,也就意味著,Lock具有比synchronized更多的功能。
其次,synchronized不需要用戶手動的釋放鎖,但是Lock需要手動釋放,如果不釋放有可能會造成死鎖的發(fā)生。
synchronized其實(shí)是有許多缺點(diǎn)的:第一,當(dāng)線程被阻塞時(shí),比如sleep(),其他的線程會一直等待下去,很浪費(fèi)時(shí)間;第二,對于多個(gè)線程來說,讀操作其實(shí)是可以多個(gè)線程共享的,syn就不能實(shí)現(xiàn)這個(gè)要求。第三,syn是不能知道一個(gè)線程是否能夠取得了鎖。
2.volatile關(guān)鍵字
2.1 什么意思/從內(nèi)存看作用
第一個(gè)作用就是防止指令重排,創(chuàng)建一個(gè)新的對象,第一步,分配內(nèi)存空間,第二步,初始化,第三步,指向分配的內(nèi)存地址。在單線程的時(shí)候一般不會出現(xiàn)問題,但是在多線程的時(shí)候,有可能出現(xiàn)132的情況,而volatile就可以防止該可能的發(fā)生(有序性)
第二個(gè)作用就是保證變量在多線程情況下的可見性。(可見性)
2.2和synchronized的區(qū)別
并發(fā)的3個(gè)特性便是:原子性,可見性,有序性。
而synchronized可以保證原子性。
二者不同的是,
第一:syn可以修飾方法,代碼塊,而volatile只能修飾變量
第二:正如上面所說syn可以保證原子性,可見性,但是volatile只能保證可見性
第三:二者的作用,syn是保證多個(gè)線程訪問資源的同步性,volatile是解決變量在多個(gè)線程之間的可見性。
浙公網(wǎng)安備 33010602011771號