1. 程式人生 > >Java核心技術卷一併發章節同步中鎖ReentrantLock的探究

Java核心技術卷一併發章節同步中鎖ReentrantLock的探究

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();
    }
}