Synchronized和Lock的区别

1.原始构成

(1).Syschronized是关键字,属于JVM层面。底层是通过monitor对象来完成。monitorenter:进入;monitorexit:退出。其实wait/notigy等方法也依赖monitor对象,只有在同步块或方法中才能调wait/notify等方法。

(2).Lock是具体类(java.util.concurrent.locks.Lock)是api层面的锁。

2.使用方法

(1).Synchronized 不需要用户去手动释放锁,当synchronied代码执行完后系统会自动让线程释放对锁的占用。

(2).ReentrantLock则需要用户去手动释放锁若没有主动释放锁,就有可能导致出现死锁现象。

3.等待是否可中断

(1).synchronized不可中断,除非抛出异常或者正常运行完成。

(2).ReentrantLock 可中断。可通过 设置超时方法 tryLock(long timeout,TimeUnit unit) 或 调用interrupt()方法可中断。

4.加锁是否公平

(1).synchronized 非公平锁

(2).ReentrantLock两者都可以,默认非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁。

5. 锁绑定多个条件Condition

(1).synchronized没有

(2).ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。Java代码示例如下:

/**
 * 资源类
 */
class Resource {
    private int number = 1; //A:1 B:2
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();

    public void print(String var) throws Exception{
        lock.lock();
        try{
            if("A" == var){
                // 1 判断
                while (number != 1){
                    condition1.await();
                }
                // 打印A
                System.out.println(Thread.currentThread().getName()+"\tA"+number);
                // 3 通知唤醒
                number = 2;
                condition2.signalAll();

            }else if("B" == var){
                while (number != 2){
                    condition2.await();
                }
                // 打印B
                System.out.println(Thread.currentThread().getName()+"\tB"+number);
                // 3 通知唤醒
                number = 1;
                condition2.signalAll();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

/**
 * @author Runner
 *
 * 锁绑定多个条件Condition,此示例代码实现打印完A后再打印B,然后再打印A,按此顺序循环5次
 */
public class Test {
    public static void main(String[] arg) throws InterruptedException {
        Resource resource = new Resource();

        new Thread(() ->{
            try {
                for (int i = 1; i <=5 ; i++) {
                    resource.print("A");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        new Thread(() ->{
            try {
                for (int i = 1; i <=5 ; i++) {
                    resource.print("B");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

 

你可能感兴趣的:(后端)