java之Synchronized(鎖住對象和鎖住代碼)
1、問題
Synchronized我們一般都知道是鎖,但是我們怎么區(qū)分是鎖對象還是鎖代碼呢?
2、測試Demo
package leetcode.chenyu.test;
public class Synchronized {
class Test {
public synchronized void testFirst() {
print("testFirst");
}
public void testSecond() {
synchronized(this) {
print("testSecond");
}
}
public void testThird() {
synchronized(Test.class) {
print("testThird");
}
}
public void print(String method) {
System.out.println(method + "start");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(method + "end");
}
}
class TestThread extends Thread {
public int mType = 0;
public Test mTest = null;
public TestThread(int type, Test test) {
this.mType = type;
this.mTest = test;
}
public void run() {
if (mTest == null) {
if (mType == 1) {
Test test = new Test();
test.testFirst();
}
else if (mType == 2) {
Test test = new Test();
test.testSecond();
}
else if (mType == 3) {
Test test = new Test();
test.testThird();
}
} else {
if (mType == 1) {
mTest.testFirst();
}
else if (mType == 2) {
mTest.testSecond();
}
else if (mType == 3) {
mTest.testThird();
}
}
}
}
public static void main(String[] args) {
Synchronized syn = new Synchronized();
Test test = syn.new Test();
for (int i = 0; i < 5; ++i) {
syn.new TestThread(1, null).start();
}
}
}
3、運行結果和分析
1)、按照上面的運行結果
testFirststart
testFirststart
testFirststart
testFirststart
testFirststart
testFirstend
testFirstend
testFirstend
testFirstend
testFirstend
2)、把for循環(huán)里面的代碼換如下
syn.new TestThread(2, null).start();
運行結果如下
testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondend
testSecondend
testSecondend
testSecondend
testSecondend
對于上面1)、2)、兩種情況,synchronized(this)以及非static的synchronized方法,只能防止多個線程同時執(zhí)行同一個對象的同步代碼段,鎖的是對象,也就是鎖的本身this, 由于每個線程都新構建了一個新的對象,所以加了synchronized沒有鎖住。
3)、把for循環(huán)里面的代碼換如下
syn.new TestThread(1, test).start();
syn.new TestThread(2, test).start();
運行結果都一樣如下
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
這里由于我們幾個現(xiàn)場都共用一個對象,所以對象固定了,所以就鎖住了,其它線程在沒有釋放鎖的時候,進不來。
4)、把for循環(huán)里面的代碼換如下
syn.new TestThread(3, null).start();
syn.new TestThread(3, test).start();
結果都如下
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
synchronized(Test.class)實現(xiàn)了全局鎖的效果,不管對象是不是一樣的,都是同樣的效果,就鎖住代碼了
我么一般用這個比較多。
4、總結
1、synchronized加在非靜態(tài)方法前和synchronized(this)都是鎖住了這個類的對象,如果多線程訪問,對象不同,就鎖不住,對象固定是一個,就可鎖住。
2、synchronized(類名.class)和加在靜態(tài)方法前,是鎖住了代碼塊,不管多線程訪問的時候?qū)ο笫遣皇峭粋€,能縮小代碼段的范圍就盡量縮小,能在代碼段上加同步就不要再整個方法上加同步,縮小鎖的粒度。
4、總結
作者:chen.yu
深信服三年半工作經(jīng)驗,目前就職游戲廠商,希望能和大家交流和學習,
微信公眾號:編程入門到禿頭 或掃描下面二維碼
零基礎入門進階人工智能(鏈接)