JUC併發工具五-synchronize和lock區別

1 synchronize是jvm層面,底層是monitorenter和monitorexit實現的;lock是具體類,api層面的鎖
2 synchronize不需要手動釋放鎖,當鎖住的代碼塊兒執行完後就會自動釋放。lock則需要手動調用unlock釋放鎖
3 synchronize等待不可中斷,除非拋異常或者方法正常完成。
lock可中斷,設置超時方法tryLock(timeout, timeunit)或lockInterruptibly()放代碼塊,調用interrupt()中斷
4 synchronize只能加非公平鎖,lock可以加公平鎖也可以加非公平鎖
5 synchronize只能隨機喚醒一個線程要麼全部喚醒,lock可以精確喚醒。

實現功能:從線程1開始,按照線程1,線程2,線程3的順序每個線程輪流打印從1到5,總計打印10次

/**
 * print方法
 * @param j 第幾次大循環
 * @param expectNum 執行的線程設置的標識
 * @param expectCondition 正在執行的condition
 * @param afterNum 下一個線程執行的標識
 * @param afterCondition 下個執行的condition
 * @throws InterruptedException
 */
private void print(int j, int expectNum, Condition expectCondition, int afterNum, Condition afterCondition) throws InterruptedException {
    // 加鎖
    reentrantLock.lock();
    while (number != expectNum) {
        // 當前線程設置的expectNum!=正在執行的number則進行讓步
        expectCondition.await();
    }
    // 執行打印任務
    for (int i = 0; i < 5; i ++) {
        System.out.println(j + "->" + Thread.currentThread().getName() + "->" + i);
    }
    // 設置下一個執行標誌位
    number = afterNum;
    // 喚醒後一個線程
    afterCondition.signal();
    // 釋放資源
    reentrantLock.unlock();
}

測試代碼

private volatile int number = 1;
private ReentrantLock reentrantLock = new ReentrantLock();
private Condition c1 = reentrantLock.newCondition();
private Condition c2 = reentrantLock.newCondition();
private Condition c3 = reentrantLock.newCondition();
@Test
public void multiConditionTest() throws InterruptedException {
    // 三個線程,輪流執行print方法10次
    new Thread(() -> {
        for (int i = 0; i < 10; i ++) {
            try {
                print(i, 1, c1, 2, c2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "線程1").start();

    new Thread(() -> {
        for (int i = 0; i < 10; i ++) {
            try {
                print(i, 2, c2, 3, c3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "線程2").start();

    new Thread(() -> {
        for (int i = 0; i < 10; i ++) {
            try {
                print(i, 3, c3, 1, c1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "線程3").start();
    TimeUnit.MINUTES.sleep(1);
}


測試結果
0->線程1->0
0->線程1->1
0->線程1->2
0->線程1->3
0->線程1->4
0->線程2->0
0->線程2->1
0->線程2->2
0->線程2->3
0->線程2->4
0->線程3->0
0->線程3->1
0->線程3->2
0->線程3->3
0->線程3->4
1->線程1->0
1->線程1->1
1->線程1->2
1->線程1->3
1->線程1->4
1->線程2->0
1->線程2->1
1->線程2->2
1->線程2->3
1->線程2->4
1->線程3->0
1->線程3->1
1->線程3->2
1->線程3->3
1->線程3->4
2->線程1->0
2->線程1->1
2->線程1->2
2->線程1->3
2->線程1->4
2->線程2->0
2->線程2->1
2->線程2->2
2->線程2->3
2->線程2->4
2->線程3->0
2->線程3->1
2->線程3->2
2->線程3->3
2->線程3->4
……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章