Java基礎之線程鎖相關知識總結
一、 synchronized關鍵字
1.對象鎖
a.當使用對象鎖的時候,註意要是相同的對象,並且當有線程正在訪問對象鎖內部的代碼的時候,其他線程無法訪問。(註意無法訪問的范圍)。
b.但是並不影響沒有使用對象鎖的部分的代碼的運行。
對象鎖分為兩類一個叫做synchronized代碼塊(圓括號內是普通類的對象),另外一個是sybchronized修飾普通成員方法。它們二者其實可以通過this關鍵字進項轉化。
2.類鎖
a. 當使用類鎖的時候,隻要是同一個類的對象.當有線程正在訪問類鎖內部的代碼的時候,其他線程無法訪問。(註意無法訪問的范圍)
b. 但是並不影響沒有使用類鎖的部分的代碼的運
對象鎖分為兩類一個叫做synchronized代碼塊(圓括號內是class對象),另外一個是sybchronized修飾靜態成員方法。它們二者其實可以通過class對象進項轉化。
註意: 類鎖和對象鎖之間沒有關系.
1、不使用線程鎖
如果沒有加synchronized關鍵字,會產生線程交錯運行
/** * 該類寫瞭一個test方法,先不加synchronized關鍵字 */ public class A { void test() { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } /** * 該類繼承Thread,重寫run方法調用A中的test方法 */ public class MyThread1 extends Thread{ A a; public void run() { a.test(); } } /** * 該類繼承Thread,重寫run方法調用A中的test方法 */ public class MyThread2 extends Thread{ A a; public void run() { a.test(); } } /** * 測試程序 * / public class Entrance { public static void main(String[] args) { /** * 演示沒有鎖時會產生交錯現象 */ A a = new A(); MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.a = a; t2.a = a; t1.start(); t2.start(); } } 產生如下運行結果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:0 線程:5 線程:6 線程:7 線程:8 線程:9 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
2、使用對象鎖
將A類中test方法代碼改成如下代碼,其他不變,運行測試類可以產生如下結果
/** * 該類寫瞭一個test方法,使用對象鎖 * 分別在鎖前鎖後增加代碼,演示對沒有使用對象鎖的代碼不會產生任何影響 * 且如果對象鎖被鎖住,對象鎖後面的代碼是不會運行的 */ public class A { void test() { System.out.println("線程開始"); synchronized(this) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } System.out.println("線程結束"); } } 運行測試類會產生如下結果:(註意:”線程開始“不是在對象鎖中的內容) 線程開始 線程:0 線程:1 線程開始 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程結束 線程:7 線程:8 線程:9 線程結束
使用synchronized直接修飾方法等價於synchronized(this)修飾方法內的全部代碼
/** * synchronized直接修飾方法等價於synchronized(this)修飾方法內的全部代碼 * test和test1方法是等價的 */ public class A { synchronized void test() { System.out.println("線程開始"); for(int i=0;i<10;i++) { System.out.println("線程:"+i); } System.out.println("線程結束"); } void test1() { synchronized (this) { System.out.println("線程開始"); for(int i=0;i<10;i++) { System.out.println("線程:"+i); } System.out.println("線程結束"); } } } 其他代碼是一樣的,在MyThread1和MyThread2中無論調用test還是test1,結果是一樣的,如下: 線程開始 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程結束 線程開始 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程結束
對象鎖對不同的方法也是有用的(類鎖也是如此)
/** * 類鎖對不同的方法也是有用的 */ 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中調用test方法,MyThread2中調用test1方法,運行結果如下: 方法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、使用類鎖
演示當A類中的test方法使用對象鎖時,不同對象調用test方法時對象鎖是起不到任何作用的
/** * 該類寫瞭一個test方法,使用對象鎖演示不用對象調用test方法 */ public class A { void test() { synchronized(this) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } MyThread1和MyThread2是一樣的,主要在測試程序的不同 測試程序: public class Entrance { public static void main(String[] args) { /** * 演示使用不同的對象調用test方法時,對象鎖會產生交錯現象 * 而使用類鎖則不會產生這種現象 */ 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(); } } 運行結果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:0 線程:5 線程:6 線程:7 線程:8 線程:9 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
使用類鎖會改變這種情況,無論是那個對象,隻要調用的是同一個方法就會產生鎖
/** * 該類寫瞭一個test方法,使用對象鎖演示不用對象調用test方法 * 將類A中的this改為A.class,其他代碼都不變 */ public class A { void test() { synchronized(A.class) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } 運行結果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
對象鎖分為兩類一個叫做synchronized代碼塊(圓括號內是普通類的對象),另外一個是sybchronized修飾普通成員方法。它們二者其實可以通過this關鍵字進項轉化。
/** * 該類寫瞭一個test方法,使用對象鎖演示不用對象調用test方法 * 將類A中的this改為A.class,其他代碼都不變 */ public class A { void test() { synchronized(A.class) { for(int i=0;i<10;i++) { System.out.println("線程:"+i); } } } } 運行結果: 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9 線程:0 線程:1 線程:2 線程:3 線程:4 線程:5 線程:6 線程:7 線程:8 線程:9
類鎖這對象鎖之間是沒有任何關系,互不影響互不幹涉
/** * 該類寫瞭test方法使用對象鎖,寫瞭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調用test方法,使用對象鎖,MyThread2調用test1方法,使用類鎖 測試程序 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(); /* 使用同一個對象調用test和test1會產生交錯現象 使用不同對象調用test和test1也會產生交錯現象 */ // t1.a = a1; // t2.a = a1; t1.a = a1; t2.a = a2; t1.start(); t2.start(); } } 運行結果: 方法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
到此這篇關於Java基礎之線程鎖相關知識總結的文章就介紹到這瞭,更多相關Java線程鎖內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!