Java核心技術卷一併發章節同步中鎖ReentrantLock的探究
阿新 • • 發佈:2019-01-25
package com.company; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 學習《Java核心技術 卷一》併發章節,同步內容。 * 關於ReentrantLock的使用。 */ public class ConcurrencyDemo { private Lock lock = new ReentrantLock(); /** * 不帶鎖的執行緒,在r的語句塊中,每一步都可能會被打斷。 */ public void unsynchConcurrencyTest() { for (int i = 0; i < 100; i++) { Runnable r = () -> { try { while (true) { int num = (int) (100 * Math.random()); System.out.println(num + "_19"); Thread.sleep(1000); System.out.println(num + "_21"); } } catch (InterruptedException e) { } }; Thread t = new Thread(r); t.start(); } } /** * 這是一個帶鎖的執行緒demo。 * 可以看出: * 第一個迴圈開始的時候(也就是第一格執行緒被建立,一共有10個Thread被建立), * 第一格Thread為:Thread[Thread-6,5,main] * 在lock()之後,sleep()期間,執行下一個執行緒。 * (猜測是t.start()之後先不管了,就是執行run,然後在開始下一個Thread,也就是這一套程式只會執行t.start(),把執行緒都啟動/建立, * 接下來的就是執行緒自己run) * 在sleep()的時候,其他執行緒準備闖入執行, * 首先是其他執行緒請求獲取鎖,然後發現沒有unlock,於是被阻塞。藉著其他的Thread請求,但是都在lock的地方被阻塞。 * 接下來就T這個擁有鎖的Thread(Thread[Thread-6,5,main])開始執行,知道unlock。 * 但是這個程式並沒有unlock,所以一直都會處於Thread[Thread-6,5,main]這個執行緒中。 * * 輸出的片段: * Thread[Thread-6,5,main]:Try to get lock... * Thread[Thread-8,5,main]:Try to get lock... * 31 * Thread[Thread-1,5,main]:Try to get lock... * Thread[Thread-2,5,main]:Try to get lock... * Thread[Thread-0,5,main]:Try to get lock... * Thread[Thread-7,5,main]:Try to get lock... * Thread[Thread-5,5,main]:Try to get lock... * Thread[Thread-9,5,main]:Try to get lock... * Thread[Thread-4,5,main]:Try to get lock... * Thread[Thread-3,5,main]:Try to get lock... * 31 * Thread[Thread-6,5,main]:loop done... * 27 * 27 * Thread[Thread-6,5,main]:loop done... * 23 * 23 * Thread[Thread-6,5,main]:loop done... * 5 * 5 * Thread[Thread-6,5,main]:loop done... * 25 */ public void lockOneConcurrencyTest() { for (int i = 0; i < 10; i++) { Runnable r = () -> { try { var cur = Thread.currentThread(); System.out.println(cur + ":Try to get lock..."); lock.lock(); while (true) { int num = (int) (100 * Math.random()); System.out.println(num); Thread.sleep(1000); System.out.println(num); System.out.println(cur + ":loop done..."); } } catch (InterruptedException e) { } finally { lock.unlock(); System.out.println("Free lock..."); } }; Thread t = new Thread(r); t.start(); } } /** * 確保每一次while都能夠被完整的執行而不被打斷。 * * 每一個程式在請求鎖的時候,如果它持有,那麼就會先呼叫持有的那段程式碼,執行完之後,才會執行本段申請鎖的之後的程式碼。 * 也就是持有計數(hold count)機制,可重入機制(reentrant)。 * * 可以從輸出看出,在Got lock之前會有執行緒執行Try to get lock... * 也就是隻有lock()到unlock()區間的程式碼被保護。 * 在其他執行緒即將執行這一段程式碼(lock()和unlock()之間的程式碼)的時候, * 就會被阻塞,直到前一個呼叫lock的那一段執行完之後這一段才會被執行。 * * 輸出: * * C:\ForProgram\jdk-10.0.2\bin\java.exe "-javaagent:C:\ForProgram\JetBrains\IntelliJ IDEA Community Edition 2018.1.1\lib\idea_rt.jar=7209:C:\ForProgram\JetBrains\IntelliJ IDEA Community Edition 2018.1.1\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\WuJing\Desktop\Learn\Java\ReviewJava\Blobs\out\production\Blobs com.company.ConcurrencyDemo * Thread[Thread-2,5,main]:Try to get lock... * Thread[Thread-9,5,main]:Try to get lock... * Thread[Thread-8,5,main]:Try to get lock... * Thread[Thread-6,5,main]:Try to get lock... * Thread[Thread-8,5,main]:Got lock... * Thread[Thread-4,5,main]:Try to get lock... * Thread[Thread-3,5,main]:Try to get lock... * Thread[Thread-1,5,main]:Try to get lock... * Thread[Thread-5,5,main]:Try to get lock... * 7 * Thread[Thread-0,5,main]:Try to get lock... * Thread[Thread-7,5,main]:Try to get lock... * 7 * Thread[Thread-8,5,main]:loop done... * Thread[Thread-6,5,main]:Got lock... * Free lock... * 45 * Thread[Thread-8,5,main]:Try to get lock... * 45 * Thread[Thread-6,5,main]:loop done... * Free lock... * Thread[Thread-6,5,main]:Try to get lock... * Thread[Thread-9,5,main]:Got lock... * 58 * 58 * Thread[Thread-9,5,main]:loop done... * Free lock... * Thread[Thread-9,5,main]:Try to get lock... * Thread[Thread-4,5,main]:Got lock... * 13 * 13 * Thread[Thread-4,5,main]:loop done... * Free lock... * Thread[Thread-4,5,main]:Try to get lock... * Thread[Thread-4,5,main]:Got lock... * 99 * 99 * Thread[Thread-4,5,main]:loop done... * Free lock... * Thread[Thread-4,5,main]:Try to get lock... * Thread[Thread-3,5,main]:Got lock... * 11 * 11 * Thread[Thread-3,5,main]:loop done... * Free lock... * Thread[Thread-3,5,main]:Try to get lock... * Thread[Thread-2,5,main]:Got lock... * 72 * 72 * Thread[Thread-2,5,main]:loop done... * Free lock... * Thread[Thread-1,5,main]:Got lock... * Thread[Thread-2,5,main]:Try to get lock... * 12 * 12 * Thread[Thread-1,5,main]:loop done... * Free lock... * Thread[Thread-1,5,main]:Try to get lock... * Thread[Thread-5,5,main]:Got lock... * 68 * 68 * Thread[Thread-5,5,main]:loop done... * Thread[Thread-0,5,main]:Got lock... * 38 * Free lock... * Thread[Thread-5,5,main]:Try to get lock... * 38 * Thread[Thread-0,5,main]:loop done... * Free lock... * Thread[Thread-0,5,main]:Try to get lock... * Thread[Thread-0,5,main]:Got lock... * 2 * 2 * Thread[Thread-0,5,main]:loop done... * Free lock... * Thread[Thread-0,5,main]:Try to get lock... * Thread[Thread-7,5,main]:Got lock... * 8 * 8 * Thread[Thread-7,5,main]:loop done... * Free lock... * Thread[Thread-8,5,main]:Got lock... * Thread[Thread-7,5,main]:Try to get lock... * 24 * 24 * Thread[Thread-8,5,main]:loop done... * Free lock... * Thread[Thread-6,5,main]:Got lock... * 9 * Thread[Thread-8,5,main]:Try to get lock... * * Process finished with exit code -1 * */ public void lockConcurrencyTest() { for (int i = 0; i < 10; i++) { Runnable r = () -> { while (true) { try { var cur = Thread.currentThread(); System.out.println(cur + ":Try to get lock..."); lock.lock(); System.out.println(cur + ":Got lock..."); int num = (int) (100 * Math.random()); System.out.println(num); Thread.sleep(1000); System.out.println(num); System.out.println(cur + ":loop done..."); } catch (InterruptedException e) { } finally { lock.unlock(); System.out.println("Free lock..."); } } }; Thread t = new Thread(r); t.start(); } } public static void main(String[] args) { ConcurrencyDemo c = new ConcurrencyDemo(); c.lockConcurrencyTest(); } }