歡迎點贊閱讀,一同窗習交流,有疑問請留言 。
GitHub上也有開源 JavaHouse,歡迎starjava
當開發過程當中,咱們遇到併發問題。怎麼解決?git
一種解決方式,簡單粗暴:上鎖。將千軍萬馬都給攔下來,只容許一我的過獨木橋。書面意思就是將並行的程序變成串行的程序。現實的鎖有門鎖、掛鎖和抽屜鎖等等。在Java中,咱們的鎖就是synchronized關鍵字和Lock接口。github
synchronized也叫同步鎖,是Java裏面的關鍵字。咱們能夠猜想到synchronized原理也JVM虛擬機有關聯。編程
synchronized鎖的是對象。對象裏面有一個叫作監視鎖(monitor)的東西,監視鎖依賴操做系統的互斥鎖(Mutex Lock)。操做系統切換線程其實就是從用戶態編程核心態(cpu的兩種狀態)。這個代價有點高,因此synchronized這個重量級鎖後面也引進了偏向鎖和輕量級鎖。安全
加鎖(監視鎖monitor)過程分析():微信
線程A能夠重複進入該monitor,因此synchronized是可重入鎖,和Lock實現的鎖同樣。併發
public class SynchronizedTest { private static int i = 0; public static void main(String[] args) { test(); } public static void test(){ synchronized (SynchronizedTest.class){ synchronized (SynchronizedTest.class){ i++; } } } }
synchronized能夠修飾方法以及代碼塊,代碼塊就是上面重入鎖的例子。ide
public class SynchronizedTest { static int n = 100; final static CountDownLatch start = new CountDownLatch(n); private static int i = 0; public static void main(String[] args) throws InterruptedException { for (int j = 0; j < n; j++) { Thread thread = new Thread(new addNoSynchronized()); thread.start(); } start.await(); System.out.println(i); } public static class addSynchronized implements Runnable{ @Override public void run() { addSynchronized(); } public static synchronized void addSynchronized(){ for (int j = 0; j < 1000; j++) { i++; } start.countDown(); } } }
100000
若是去掉 synchronized 關鍵字的話,運行結果大機率不是 100000,由於線程不安全問題。學習
通常咱們使用 ReentrantLock 類做爲重入鎖,實現Lock接口。操作系統
public class ReentranLockTest { private static int j; private static int n = 100; private static CountDownLatch latch = new CountDownLatch(n); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < n; i++) { new Thread(new LockTest()).start(); } latch.await(); System.out.println("結果爲:"+j); } public static class LockTest implements Runnable{ static Lock lock = new ReentrantLock(); @Override public void run() { lockTest(); latch.countDown(); } private void lockTest() { lock.lock(); try { for (int i = 0; i < 1000; i++) { j++; } }finally { lock.unlock(); } } } }
結果爲:100000
這裏咱們鎖住的 j++ 這塊資源區(公共資源),lock 是 static 關鍵字修飾的,是類對象,思考一下若是不是類對象會怎麼樣?那就是連環鎖了(看圖)。
每個線程都對能夠用鑰匙解開這把鎖,對於程序而言,加鎖操做就沒有意義了。由於咱們須要的是一個鎖。