Java中實(shí)例方法和靜態(tài)方法在多線程下加鎖和不加鎖

第一個例子是同一實(shí)例方法加鎖和不加鎖在多線程情況下的訪問情況,代碼如下:

package test.caipiao.log;

/**

* 一個類的同一個實(shí)例,方法加鎖和不加鎖情況下的訪問情況.

* @author lfl

*

*/

public class Test {

public static void main(String[] args) {

final TT tt = new TT();

Thread t1 = new Thread() {

public void run() {

tt.test(); //調(diào)用加鎖的test()

}

};

Thread t2 = new Thread() {

public void run() {

tt.test2(); //調(diào)用加鎖的test2()

}

};

Thread t3 = new Thread() {

public void run() {

tt.test3(); //調(diào)用不加鎖的test3()

}

};

/**

* t1 t2 t3 三個線程依次啟動運(yùn)行.

*/

t1.start();

t2.start();

t3.start();

System.out.println("over");

}

}

class TT {

public synchronized void test() {

for (int i = 0; i < 10000000; i++) {

if (i % 10000 == 0) {

System.out.println(i +"---");

}

}

}

public synchronized void test2() {

System.out.println("test2");

}

public void test3() {

System.out.println("test3");

}

}

輸出如下(多次運(yùn)行和不同計(jì)算機(jī)上運(yùn)行輸出結(jié)果可能不一樣):

over 0 --- test3 10000 --- 20000 --- 30000 --- 40000 --- 50000 --- 60000 ---

......

9910000 --- 9920000 --- 9930000 --- 9940000 --- 9950000 --- 9960000 --- 9970000 --- 9980000 --- 9990000 --- test2

說明:

主線程先輸出 over,主線程沒有持有tt上的鎖,這里就不關(guān)心了。

t1線程輸出0,此時還在持有tt上的鎖,t3線程就輸出test3,說明線程t1持有tt上的鎖,而不影響t3線程調(diào)用test3()方法,即允許其它線程方法訪問該實(shí)例的非加鎖方法。而最后輸出test2,是在線程t1釋放了tt上的鎖后

線程t3獲得tt上的鎖才能調(diào)用test2()方法,即一個線程持有當(dāng)前實(shí)例的鎖,其它線程不能訪問該實(shí)例的加鎖方法。

-------------------------------分割線-------------------------------------------------

第二個例子是靜態(tài)方法加鎖和不加鎖在多線程情況下的訪問情況,代碼如下:

package test.caipiao.log;

/**

* 一個類的同一個實(shí)例,方法加鎖和不加鎖情況下的訪問情況.

* @author lfl

*

*/

public class TestStatic {

public static void main(String[] args) {

final TTStatic tt = new TTStatic();

Thread t1 = new Thread() {

public void run() {

TTStatic.test(); //調(diào)用加鎖的test()

}

};

Thread t2 = new Thread() {

public void run() {

TTStatic.test2(); //或者

tt.test2(); //調(diào)用加鎖的test2()

}

};

Thread t3 = new Thread() {

public void run() {

TTStatic.test3(); //調(diào)用不加鎖的test3()

}

};

/**

* t1 t2 t3 三個線程依次啟動運(yùn)行.

*/

t1.start();

t2.start();

t3.start();

System.out.println("over");

}

}

class TTStatic {

public static synchronized void test() {

for (int i = 0; i < 10000000; i++) {

if (i % 10000 == 0) {

System.out.println(i +"---");

}

}

}

public static synchronized void test2() {

System.out.println("test2");

}

public static void test3() {

System.out.println("test3");

}

}

輸出如下(多次運(yùn)行和不同計(jì)算機(jī)上運(yùn)行輸出結(jié)果可能不一樣):

0 ---

10000 ---

20000 ---

30000 ---

40000 ---

50000 ---

60000 ---

70000 ---

80000 ---

90000 ---

test3

over

100000 ---

110000 ---

120000 ---

130000 ---

......

9920000 ---

9930000 ---

9940000 ---

9950000 ---

9960000 ---

9970000 ---

9980000 ---

9990000 ---

test2

test2

說明:

基本同第一個例子的分析一樣,只不過這里線程持有的是TTStatic class對象上的鎖,而TTStatic class對象只有一個。需要說明的是最后輸出的兩個test2,這個說明調(diào)用靜態(tài)的加鎖方法,不論是用類名調(diào)用還是實(shí)例調(diào)用,都需要獲得該類的class對象上的鎖。

-------------------------------------------分割線------------------------------------------------------

第三個例子是同一實(shí)例方法加鎖和不加鎖在多線程情況下和靜態(tài)方法加鎖和不加鎖在多線程情況下的訪問情況,代碼如下:

package test.caipiao.log;

/**

* 一個類的同一個實(shí)例,方法加鎖和不加鎖情況下的訪問情況.

* @author lfl

*

*/

public class TestHybrid {

public static void main(String[] args) {

Thread t1 = new Thread() {

public void run() {

TTHybrid.test(); //調(diào)用加鎖的test()

}

};

Thread t2 = new Thread() {

public void run() {

TTHybrid.test2(); //調(diào)用加鎖的test2()

}

};

Thread t3 = new Thread() {

public void run() {

TTHybrid.test3(); //調(diào)用不加鎖的test3()

}

};

//下面是非靜態(tài)方法調(diào)用

final TTHybrid tt = new TTHybrid();

Thread t4 = new Thread() {

public void run() {

tt.test4(); //調(diào)用加鎖的test4()

}

};

Thread t5 = new Thread() {

public void run() {

tt.test5(); //調(diào)用加鎖的test5()

}

};

Thread t6 = new Thread() {

public void run() {

tt.test6(); //調(diào)用不加鎖的test6()

}

};

/**

* t1 t2 t3 三個線程依次啟動運(yùn)行.

*/

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

t6.start();

System.out.println("over");

}

}

class TTHybrid {

public static synchronized void test() {

for (int i = 0; i < 10000000; i++) {

if (i % 10000 == 0) {

System.out.println(i +"--- static");

}

}

}

public static synchronized void test2() {

System.out.println("test2");

}

public static void test3() {

System.out.println("test3");

}

public synchronized void test4() {

for (int i = 0; i < 10000000; i++) {

if (i % 10000 == 0) {

System.out.println(i +"--- instance");

}

}

}

public synchronized void test5() {

System.out.println("test5");

}

public void test6() {

System.out.println("test6");

}

}

輸出如下(多次運(yùn)行和不同計(jì)算機(jī)上運(yùn)行輸出結(jié)果可能不一樣):

0 --- static

over

test3

0 --- instance

10000 --- static

10000 --- instance

20000 --- instance

30000 --- instance

20000 --- static

40000 --- instance

50000 --- instance

30000 --- static

60000 --- instance

40000 --- static

50000 --- static

60000 --- static

70000 --- instance

test6

90000 --- static

100000 --- instance

100000 --- static

110000 --- static

120000 --- static

110000 --- instance

130000 --- static

120000 --- instance

140000 --- static

130000 --- instance

150000 --- static

......

9960000 --- instance

9370000 --- static

9970000 --- instance

9380000 --- static

9980000 --- instance

9390000 --- static

9990000 --- instance

9400000 --- static

9410000 --- static

test5

9420000 --- static

9430000 --- static

......

9970000 --- static

9980000 --- static

9990000 --- static

test2

說明:

主線程輸出的over,t3線程輸出的test3和t6線程輸出的test6,可以看到無論是否是靜態(tài)的,持有相應(yīng)的鎖對該類方法的訪問沒有影響。接著可以看到test()和test4()方法,基本是交替調(diào)用輸出的,這說明持有TTHybrid class 對象上的鎖和持有tt上的鎖是沒有直接關(guān)系的,即持有TTHybrid class 對象上的鎖訪問靜態(tài)方法不會影響持有tt上的鎖訪問非靜態(tài)方法。test4()輸出完畢后釋放tt上的鎖 后,test5()方法開始輸出。test()輸出完畢后釋放TTHybrid class 對象上的鎖 后,test2()方法開始輸出。

通過這三個小例子應(yīng)該對Java中實(shí)例方法和靜態(tài)方法在多線程下加鎖和不加鎖的訪問情況有了一定的了解。關(guān)于synchronized關(guān)鍵字的具體含義請參看其它相關(guān)資料。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,623評論 18 399
  • 文章來源:http://www.54tianzhisheng.cn/2017/06/04/Java-Thread/...
    beneke閱讀 1,877評論 0 1
  • 一、 1、請用Java寫一個冒泡排序方法 【參考答案】 public static void Bubble(int...
    獨(dú)云閱讀 1,494評論 0 6
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,584評論 1 15
  • 【20170416G152班班會分享“執(zhí)行”】 大家都知道,行動三角形,收集,排程,執(zhí)行,是無論在葉老師的哪種課程...
    桃樂茜314閱讀 569評論 0 4

友情鏈接更多精彩內(nèi)容