Java基礎(chǔ)之線程鎖相關(guān)知識(shí)總結(jié)
一、 synchronized關(guān)鍵字
1.對(duì)象鎖
a.當(dāng)使用對(duì)象鎖的時(shí)候,注意要是相同的對(duì)象,并且當(dāng)有線程正在訪問對(duì)象鎖內(nèi)部的代碼的時(shí)候,其他線程無法訪問。(注意無法訪問的范圍)。
b.但是并不影響沒有使用對(duì)象鎖的部分的代碼的運(yùn)行。
對(duì)象鎖分為兩類一個(gè)叫做synchronized代碼塊(圓括號(hào)內(nèi)是普通類的對(duì)象),另外一個(gè)是sybchronized修飾普通成員方法。它們二者其實(shí)可以通過this關(guān)鍵字進(jìn)項(xiàng)轉(zhuǎn)化。
2.類鎖
a. 當(dāng)使用類鎖的時(shí)候,只要是同一個(gè)類的對(duì)象.當(dāng)有線程正在訪問類鎖內(nèi)部的代碼的時(shí)候,其他線程無法訪問。(注意無法訪問的范圍)
b. 但是并不影響沒有使用類鎖的部分的代碼的運(yùn)
對(duì)象鎖分為兩類一個(gè)叫做synchronized代碼塊(圓括號(hào)內(nèi)是class對(duì)象),另外一個(gè)是sybchronized修飾靜態(tài)成員方法。它們二者其實(shí)可以通過class對(duì)象進(jìn)項(xiàng)轉(zhuǎn)化。
注意: 類鎖和對(duì)象鎖之間沒有關(guān)系.
1、不使用線程鎖
如果沒有加synchronized關(guān)鍵字,會(huì)產(chǎn)生線程交錯(cuò)運(yùn)行
/** * 該類寫了一個(gè)test方法,先不加synchronized關(guān)鍵字 */ public class A { void test() { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } /** * 該類繼承Thread,重寫run方法調(diào)用A中的test方法 */ public class MyThread1 extends Thread{ A a; public void run() { a.test(); } } /** * 該類繼承Thread,重寫run方法調(diào)用A中的test方法 */ public class MyThread2 extends Thread{ A a; public void run() { a.test(); } } /** * 測(cè)試程序 * / public class Entrance { public static void main(String[] args) { /** * 演示沒有鎖時(shí)會(huì)產(chǎn)生交錯(cuò)現(xiàn)象 */ A a = new A(); MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.a = a; t2.a = a; t1.start(); t2.start(); } } 產(chǎn)生如下運(yùn)行結(jié)果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:0 線程:5 線程:6 線程:7 線程:8 線程:9 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
2、使用對(duì)象鎖
將A類中test方法代碼改成如下代碼,其他不變,運(yùn)行測(cè)試類可以產(chǎn)生如下結(jié)果
/** * 該類寫了一個(gè)test方法,使用對(duì)象鎖 * 分別在鎖前鎖后增加代碼,演示對(duì)沒有使用對(duì)象鎖的代碼不會(huì)產(chǎn)生任何影響 * 且如果對(duì)象鎖被鎖住,對(duì)象鎖后面的代碼是不會(huì)運(yùn)行的 */ public class A { void test() { System.out.println("線程開始"); synchronized(this) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } System.out.println("線程結(jié)束"); } } 運(yùn)行測(cè)試類會(huì)產(chǎn)生如下結(jié)果:(注意:”線程開始“不是在對(duì)象鎖中的內(nèi)容) 線程開始 線程:0 線程:1 線程開始 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程結(jié)束 線程:7 線程:8 線程:9 線程結(jié)束
使用synchronized直接修飾方法等價(jià)于synchronized(this)修飾方法內(nèi)的全部代碼
/** * synchronized直接修飾方法等價(jià)于synchronized(this)修飾方法內(nèi)的全部代碼 * test和test1方法是等價(jià)的 */ public class A { synchronized void test() { System.out.println("線程開始"); for(int i=0;i<10;i++) { System.out.println("線程:"+i); } System.out.println("線程結(jié)束"); } void test1() { synchronized (this) { System.out.println("線程開始"); for(int i=0;i<10;i++) { System.out.println("線程:"+i); } System.out.println("線程結(jié)束"); } } } 其他代碼是一樣的,在MyThread1和MyThread2中無論調(diào)用test還是test1,結(jié)果是一樣的,如下: 線程開始 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程結(jié)束 線程開始 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程結(jié)束
對(duì)象鎖對(duì)不同的方法也是有用的(類鎖也是如此)
/** * 類鎖對(duì)不同的方法也是有用的 */ public class A { // synchronized void test() { // for(int i=0;i<10;i++) { // System.out.println("方法test:"+i); // } // } void test() { synchronized(this) { for(int i=0;i<10;i++) { System.out.println("方法test:"+i); } } } // synchronized void test1() { // for(int i=0;i<10;i++) { // System.out.println("方法test1:"+i); // } // } void test1() { synchronized(this) { for(int i=0;i<10;i++) { System.out.println("方法test1:"+i); } } } } MyThread1中調(diào)用test方法,MyThread2中調(diào)用test1方法,運(yùn)行結(jié)果如下: 方法test:0 方法test:1 方法test:2 方法test:3 方法test:4 方法test:5 方法test:6 方法test:7 方法test:8 方法test:9 方法test1:0 方法test1:1 方法test1:2 方法test1:3 方法test1:4 方法test1:5 方法test1:6 方法test1:7 方法test1:8 方法test1:9
3、使用類鎖
演示當(dāng)A類中的test方法使用對(duì)象鎖時(shí),不同對(duì)象調(diào)用test方法時(shí)對(duì)象鎖是起不到任何作用的
/** * 該類寫了一個(gè)test方法,使用對(duì)象鎖演示不用對(duì)象調(diào)用test方法 */ public class A { void test() { synchronized(this) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } MyThread1和MyThread2是一樣的,主要在測(cè)試程序的不同 測(cè)試程序: public class Entrance { public static void main(String[] args) { /** * 演示使用不同的對(duì)象調(diào)用test方法時(shí),對(duì)象鎖會(huì)產(chǎn)生交錯(cuò)現(xiàn)象 * 而使用類鎖則不會(huì)產(chǎn)生這種現(xiàn)象 */ A a1 = new A(); A a2 = new A(); MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.a = a1; t2.a = a2; t1.start(); t2.start(); } } 運(yùn)行結(jié)果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:0 線程:5 線程:6 線程:7 線程:8 線程:9 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
使用類鎖會(huì)改變這種情況,無論是那個(gè)對(duì)象,只要調(diào)用的是同一個(gè)方法就會(huì)產(chǎn)生鎖
/** * 該類寫了一個(gè)test方法,使用對(duì)象鎖演示不用對(duì)象調(diào)用test方法 * 將類A中的this改為A.class,其他代碼都不變 */ public class A { void test() { synchronized(A.class) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } 運(yùn)行結(jié)果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
對(duì)象鎖分為兩類一個(gè)叫做synchronized代碼塊(圓括號(hào)內(nèi)是普通類的對(duì)象),另外一個(gè)是sybchronized修飾普通成員方法。它們二者其實(shí)可以通過this關(guān)鍵字進(jìn)項(xiàng)轉(zhuǎn)化。
/** * 該類寫了一個(gè)test方法,使用對(duì)象鎖演示不用對(duì)象調(diào)用test方法 * 將類A中的this改為A.class,其他代碼都不變 */ public class A { void test() { synchronized(A.class) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } 運(yùn)行結(jié)果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
類鎖這對(duì)象鎖之間是沒有任何關(guān)系,互不影響互不干涉
/** * 該類寫了test方法使用對(duì)象鎖,寫了test1方法使用類鎖 */ public class A { synchronized void test() { for(int i=0;i<10;i++) { System.out.println("方法test:"+i); } } synchronized static void test1() { for(int i=0;i<10;i++) { System.out.println("方法test1:"+i); } } } MyThread1調(diào)用test方法,使用對(duì)象鎖,MyThread2調(diào)用test1方法,使用類鎖 測(cè)試程序 public class Entrance { public static void main(String[] args) { A a1 = new A(); A a2 = new A(); MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); /* 使用同一個(gè)對(duì)象調(diào)用test和test1會(huì)產(chǎn)生交錯(cuò)現(xiàn)象 使用不同對(duì)象調(diào)用test和test1也會(huì)產(chǎn)生交錯(cuò)現(xiàn)象 */ // t1.a = a1; // t2.a = a1; t1.a = a1; t2.a = a2; t1.start(); t2.start(); } } 運(yùn)行結(jié)果: 方法test:0 方法test:1 方法test1:0 方法test1:1 方法test1:2 方法test1:3 方法test1:4 方法test1:5 方法test1:6 方法test1:7 方法test1:8 方法test1:9 方法test:2 方法test:3 方法test:4 方法test:5 方法test:6 方法test:7 方法test:8 方法test:9
到此這篇關(guān)于Java基礎(chǔ)之線程鎖相關(guān)知識(shí)總結(jié)的文章就介紹到這了,更多相關(guān)Java線程鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入學(xué)習(xí)Spring Cloud-Ribbon
這篇文章主要介紹了Spring Cloud-Ribbon的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友一起看看吧2021-03-03Spring配置多個(gè)數(shù)據(jù)源并實(shí)現(xiàn)動(dòng)態(tài)切換示例
本篇文章主要介紹了Spring配置多個(gè)數(shù)據(jù)源并實(shí)現(xiàn)動(dòng)態(tài)切換示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04sms4j?2.0?全新來襲功能的調(diào)整及maven變化詳解
這篇文章主要介紹了sms4j?2.0?全新來襲功能的調(diào)整及maven變化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04javaweb購(gòu)物車案列學(xué)習(xí)開發(fā)
這篇文章主要為大家詳細(xì)介紹了javaweb購(gòu)物車案列學(xué)習(xí)開發(fā)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05RestTemplate如何通過HTTP?Basic?Auth認(rèn)證示例說明
這篇文章主要為大家介紹了RestTemplate如何通過HTTP?Basic?Auth認(rèn)證的示例說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03Spring Framework遠(yuǎn)程代碼執(zhí)行漏洞分析(最新漏洞)
Spring Framework 是一個(gè)開源應(yīng)用框架,旨在降低應(yīng)用程序開發(fā)的復(fù)雜度,它具有分層體系結(jié)構(gòu),允許用戶選擇組件,同時(shí)還為 J2EE 應(yīng)用程序開發(fā)提供了一個(gè)有凝聚力的框架,對(duì)Spring遠(yuǎn)程代碼執(zhí)行漏洞相關(guān)知識(shí)感興趣的朋友一起看看吧2022-04-04