Synchronized和Lock区别

不打扰是莪最后的温柔 提交于 2019-12-22 18:31:31

1构成

Synchronized是关键字属于JVM层面。
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要么随机唤醒一个线程,要么唤醒全部线程。

做个小题来理解Condition

《绑定多个条件condition实现精确唤醒》
多线程之间按顺序调用,实现A->B->C三个线程启动,要求A线程打印2次,B线程打印5次,C线程打印7次循环打印2轮

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

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 print2() {
        lock.lock();
        try {
            //1.判断
            while (number != 1) {
                c1.await();
            }
            //2.干活
            for (int i = 1; i <= 2; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //3.通知
            number = 2;
            c2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print5() {
        lock.lock();
        try {
            //1.判断
            while (number != 2) {
                c2.await();
            }
            //2.干活
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //3.通知
            number = 3;
            c3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print7() {
        lock.lock();
        try {
            //1.判断
            while (number != 3) {
                c3.await();
            }
            //2.干活
            for (int i = 1; i <= 7; 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 <= 2; i++) {
                shareResource.print2();
            }
        }, "A").start();

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

        new Thread(() -> {
            for (int i = 1; i <= 2; i++) {
                shareResource.print7();
            }
        }, "C").start();
    }
}

运行结果:
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!