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
……

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