synchronized 和 lock 有什麼區別?用新的 lock 有什麼好處?-----你應該瞭解的

1、原始構成

synchronized 是關鍵字屬於 JVM 層面,
           monitorenter(底層是通過 monitor 對象來完成, 其實 wait/notify 等方法也依賴於 monitor 對象只有在同步塊或方法中才能調 wait/notify 等方法)
           monitorexit
Lock 是具體類(java.util.concurrent.locks.Lock)是 api 層面的鎖

2、使用方法

synchronized 不需要用戶去手動釋放鎖,當 synchronized 代碼執行完後系統會自動讓線程釋放對鎖的佔用
ReentrantLock 則需要用戶去手動釋放鎖若沒有主動釋放鎖,就有可能導致出現死鎖現象。
   需要 lock() 和 unlock() 方法配合 try / finally 語句塊來完成。

3、等待是否可中斷

synchronized 不可中斷,除非拋出異常或者正常運行完成
ReentrantLock 可中斷,1、設置超時方法 tryLock(long timeout, TimeUnit unit)
                                       2、lockInterruptibly() 放代碼塊這,調用 interrupt() 方法可中斷

4、加鎖是否公平

synchronized 非公平鎖
ReentrantLock 兩者都可以,默認非公平鎖,構造方法可以傳入 boolean 值,true 爲公平鎖,false 爲非公平鎖

5、鎖綁定多個條件 Condition

synchronized 沒有
ReentrantLock 用來實現分組喚醒需要喚醒的線程們,可以精神喚醒,而不是像 synchronized 要麼隨機喚醒一個線程要麼喚醒全部線程。

package com.brian.interview.study.thread;

/**
 * Copyright (c) 2020 ZJU All Rights Reserved
 * <p>
 * Project: JavaSomeDemo
 * Package: com.brian.interview.study.thread
 * Version: 1.0
 * <p>
 * Created by Brian on 2020/2/12 23:03
 */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 題目:synchronized 和 lock 有什麼區別?用新的 lock 有什麼好處?你舉例說說
 * 1、原始構成
 *    synchronized 是關鍵字屬於 JVM 層面,
 *       monitorenter(底層是通過 monitor 對象來完成, 其實 wait/notify 等方法也依賴於 monitor 對象只有在同步塊或方法中才能調 wait/notify 等方法)
 *       monitorexit
 *    Lock 是具體類 (java.util.concurrent.locks.Lock) 是 api 層面的鎖
 *
 * 2、使用方法
 *    synchronized 不需要用戶去手動釋放鎖, 當 synchronized 代碼執行完後系統會自動讓線程釋放對鎖的佔用
 *    ReentrantLock 則需要用戶去手動釋放鎖若沒有主動釋放鎖, 就有可能導致出現死鎖現象。
 *     需要 lock() 和 unlock() 方法配合 try/finally 語句塊來完成。
 *
 * 3、等待是否可中斷
 *    synchronized 不可中斷, 除非拋出異常或者正常運行完成
 *    ReentrantLock 可中斷, 1、設置超時方法 tryLock(long timeout, TimeUnit unit)
 *                         2、lockInterruptibly() 放代碼塊中, 調用 interrupt() 方法可中斷
 *
 * 4、加鎖是否公平
 *    synchronized 非公平鎖
 *    ReentrantLock 兩者都可以, 默認非公平鎖, 構造方法可以傳入 boolean 值, true 爲公平鎖, false 爲非公平鎖
 *
 * 5、鎖綁定多個條件 Condition
 *    synchronized 沒有
 *    ReentrantLock 用來實現分組喚醒需要喚醒的線程們, 可以精神喚醒, 而不是像 synchronized 要麼隨機喚醒一個線程要麼喚醒全部線程。
 *
 * ===================================================================================================================
 * ===================================================================================================================
 * ===================================================================================================================
 *
 * 題目:多線程之間按順序調用, 實現 A->B->C 三個線程啓動, 要求如下:
 * AA打印5次, BB打印10次, CC打印15次
 * 緊接着
 * AA打印5次, BB打印10次, CC打印15次
 * ......
 * 來10輪
 *
 *
 */

class ShareResource{
    private int number = 1;  // A:1   B:2   C:3
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(){
        lock.lock();
        try {
            // 1、判斷
            while(number != 1){
                c1.await();
            }

            // 2、幹活
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            // 3、通知
            number = 2;
            c2.signal();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try {
            // 1、判斷
            while(number != 2){
                c2.await();
            }

            // 2、幹活
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            // 3、通知
            number = 3;
            c3.signal();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try {
            // 1、判斷
            while(number != 3){
                c3.await();
            }

            // 2、幹活
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            // 3、通知
            number = 1;
            c1.signal();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

public class SyncAndReentrantLockDemo {
    public static void main(String[] args) {

        ShareResource shareResource = new ShareResource();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                shareResource.print5();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                shareResource.print10();
            }
        }, "BB").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                shareResource.print15();
            }
        }, "CC").start();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章