指標(biāo):理解Synchronized的含義肋杖,明確Synchronized關(guān)鍵字修飾普通方法、靜態(tài)方法和代碼塊時鎖對象的差異
1挖函、含義:Synchronized是Java中解決并發(fā)問題的一種最常見的方法兽愤,也是最簡單的一種方法。用于處理多線程中訪問相同資源造成沖突的一種同步鎖挪圾,實現(xiàn)代碼的中的同步機制。
2逐沙、作用:主要有三個作用
①確保線程互斥的訪問同步代碼塊
②保證共享變量的修改能夠及時可見
③有效解決重排序問題
3哲思、修飾對象
①修飾普通方法,其作用范圍是整個方法吩案,作用的對象是調(diào)用這個方法的對象棚赔。
②修飾靜態(tài)方法,其作用范圍是這個靜態(tài)方法徘郭,作用對象是這個類的所有對象
③修飾代碼塊靠益,其作用范圍是由{}括起來的代碼塊,作用的對象是調(diào)用這個代碼塊的對象
一個線程訪問一個對象中的synchronize同步代碼塊時残揉,試圖訪問該對象的線程將被阻塞
class SyncThread implements Runnable {
private static int count;
public SyncThread() {
count = 0;
}
public void run() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++));
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public int getCount() {
return count;
}
}
public class test {
public static void main(String[] args) {
SyncThread syncThread = new SyncThread();
Thread thread1 = new Thread(syncThread, "sycn1");
Thread thread2 = new Thread(syncThread, "sycn2");
thread1.start();
thread2.start();
}
}
上面的代碼在控制臺打印時依次等待執(zhí)行胧后,結(jié)果如下
sycn1:0
sycn1:1
sycn1:2
sycn1:3
sycn1:4
sycn2:5
sycn2:6
sycn2:7
sycn2:8
sycn2:9
當(dāng)兩個并發(fā)線程(thread1和thread2)訪問同一個對象(syncThread)中的synchronized代碼塊時,在同一時刻只能有一個線程得到執(zhí)行抱环,另一個線程受阻塞壳快,必須等待當(dāng)前線程執(zhí)行完這個代碼塊以后才能執(zhí)行該代碼塊纸巷。Thread1和thread2是互斥的,因為在執(zhí)行synchronized代碼塊時會鎖定當(dāng)前的對象眶痰,只有執(zhí)行完該代碼塊才能釋放該對象鎖瘤旨,下一個線程才能執(zhí)行并鎖定該對象
我們把SyncThread的調(diào)用修改如下:
Thread thread1 = new Thread(new SyncThread(), "sycn1");
Thread thread2 = new Thread(new SyncThread(), "sycn2");
thread1.start();
thread2.start();
執(zhí)行結(jié)果如下:
sycn1:0
sycn2:1
sycn1:2
sycn2:3
sycn2:5
sycn1:4
sycn2:6
sycn1:6
sycn1:8
sycn2:7
不是說一個線程執(zhí)行synchronized代碼塊時其它的線程受阻塞嗎?為什么上面的例子中thread1和thread2同時在執(zhí)行竖伯?
這是因為synchronized只鎖定對象存哲,每個對象只有一個鎖(lock)與之相關(guān)聯(lián),而上面的代碼等同于下面這段代碼:
SyncThread syncThread1 = new SyncThread();
SyncThread syncThread2 = new SyncThread();
Thread thread1 = new Thread(syncThread1, "SyncThread1");
Thread thread2 = new Thread(syncThread2, "SyncThread2");
thread1.start();
thread2.start();
這時創(chuàng)建了兩個SyncThread的對象syncThread1和syncThread2七婴,線程thread1執(zhí)行的是syncThread1對象中的synchronized代碼(run)祟偷,而線程thread2執(zhí)行的是syncThread2對象中的synchronized代碼(run);我們知道synchronized鎖定的是對象本姥,這時會有兩把鎖分別鎖定syncThread1對象和syncThread2對象肩袍,而這兩把鎖是互不干擾的,不形成互斥婚惫,所以兩個線程可以同時執(zhí)行
問題答案:
問題1:不同步氛赐,因為a1.a和a2.a不是同一個鎖蒋荚,鎖住的是this
問題2:同步傻盟,因為關(guān)鍵字static已經(jīng)讓這個代碼塊都添加上了同一把鎖,鎖住的是this.class