Java中synchronized的同步原理
本文介紹在java開發(fā)中,怎么利用synchronized保證代碼的同步執(zhí)行,避免跳坑,廢話不多說,直接上demo。
package com.helianxiaowu.demo; ? /** * @title synchronized同步demo * @desc 注意:為了演示方便,代碼中多線程使用直接new的方式,這種方式不可取,會造成服務器資源消耗。 * 工作中如果用到多線程,盡量使用線程池維護線程 * @author helianxiaowu * @date 2020/1/14 上午 11:12 */ public class SynchronizedDemo { ? public static void main(String[] args) { ? Demo demo = new Demo(); ? // 啟用兩條線程 Thread t1 = new Thread(() -> demo.print("Thread1")); Thread t2 = new Thread(() -> demo.print("Thread2")); t1.start(); t2.start(); } ? static class Demo { public void print(String flag) { System.out.println(flag + " start"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(flag + " end"); } } }
以上代碼的執(zhí)行結(jié)果為

現(xiàn)在我們在print方法上加上synchronized關(guān)鍵字,代碼如下

執(zhí)行結(jié)果如下,從執(zhí)行結(jié)果中我們可以看到代碼變成同步執(zhí)行了

原理
JVM為每一個類或?qū)嵗S護了一個監(jiān)視器monitor,當出現(xiàn)synchronized關(guān)鍵字時monitor會做出如下判斷
1. 判斷monitor是否已有所有者,如果沒有,則允許線程進入,并把計數(shù)器從0變?yōu)?
2. 如果monitor已經(jīng)擁有所有者,則當前線程進入等待狀態(tài),并把計數(shù)器加1
3. 當線程退出時,計數(shù)器減1。當計數(shù)器為0時,monitor失去所有者
原理搞清楚了,我們在進行深入的研究。接著對代碼進行修改,調(diào)用print方法分別使用不同的實例。修改完的代碼如下

代碼執(zhí)行結(jié)果如下,從執(zhí)行結(jié)果來看,synchronized關(guān)鍵字并沒有起到作用,這是因為什么

注意事項
synchronized使用時必須是同一個實例,因為JVM為每個實例分配了一個monitor,不同的實例是不同的monitor在監(jiān)聽,所以實現(xiàn)不了同步。保證同一個實例的方法有很多種,比如:
1. 把java對象交給spring管理
2. 使用單例模式
3. 將方法定義為靜態(tài)方法,靜態(tài)方法屬于某個類,不屬于具體的實例
-- 赫連小伍原創(chuàng),轉(zhuǎn)載請注明出處,微信公眾號同名
浙公網(wǎng)安備 33010602011771號