关于java:synchronized和Lock有什么区别

35次阅读

共计 2307 个字符,预计需要花费 6 分钟才能阅读完成。

synchronized 和 Lock 都是 Java 中用于实现线程同步的机制,它们都能够保障线程平安。

synchronized 介绍与应用

synchronized 可用来润饰一般办法、静态方法和代码块,当一个线程拜访一个被 synchronized 润饰的办法或者代码块时,会主动获取该对象的锁,其余线程将会被阻塞,直到该线程执行结束并开释锁。这样就保障了多个线程对共享资源的操作的互斥性,从而防止了数据的不一致性和线程平安问题。

synchronized 根本应用如下:

public class SynchronizedDemo {
    private int count = 0;
    public synchronized void increment() {count++;}
    public synchronized int getCount() {return count;}
}

此时咱们再应用多线程调用下面类的 increment 或 getCount 时,就不会呈现线程平安问题了,如下代码所示:

public class SynchronizedDemoTest {public static void main(String[] args) {SynchronizedDemo demo = new SynchronizedDemo();
        Runnable r = () -> {for (int i = 0; i < 1000; i++) {demo.increment();
            }
        };

        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);

        t1.start();
        t2.start();

        try {t1.join();
            t2.join();} catch (InterruptedException e) {e.printStackTrace();
        }

        System.out.println("Count:" + demo.getCount());
    }
}

Lock 介绍与应用

Lock 是一种线程同步的机制,它与 synchronized 类似,能够用于管制对共享资源的拜访。相比于 synchronized,Lock 的特点在于更加灵便,反对更多的操作。

Lock 接口定义了以下办法:

  • lock():获取锁,如果锁已被其余线程占用,则阻塞以后线程。
  • tryLock():尝试获取锁,如果锁已被其余线程占用,则返回 false,否则返回 true。
  • tryLock(long timeout, TimeUnit unit):尝试获取锁,在指定的工夫范畴内获取到锁则返回 true,否则返回 false。
  • unlock():开释锁。

相比于 synchronized,Lock 的长处在于:

  • 粒度更细:synchronized 关键字只能对整个办法或代码块进行同步,而 Lock 能够对单个变量或对象进行同步。
  • 反对偏心锁:synchronized 不反对偏心锁,而 Lock 能够通过构造函数指定锁是否是偏心锁。
  • 反对多个条件变量:Lock 能够创立多个条件变量,即多个期待队列。

Lock 的实现类有很多,比拟罕用的有 ReentrantLock 和 ReentrantReadWriteLock。

须要留神的是,应用 Lock 时须要手动获取和开释锁,否则会导致死锁等问题。因而,一般来说倡议应用 try-finally 语句块来确保锁的正确开释。例如:

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

public class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        // 加锁
        lock.lock();
        try {count++;} finally {
            // 开释锁
            lock.unlock();}
    }

    public void decrement() {
        // 加锁
        lock.lock();
        try {count--;} finally {
            // 开释锁
            lock.unlock();}
    }
    public int getCount() {return count;}
}

synchronized VS Lock

synchronized 和 Lock 次要的区别有以下几个方面:

  1. 锁的获取形式:synchronized 是隐式获取锁的,即在进入 synchronized 代码块或办法时主动获取锁,退出时主动开释锁;而 Lock 须要程序显式地获取锁和开释锁,即须要调用 lock() 办法获取锁,调用 unlock() 办法开释锁。
  2. 锁的性质:synchronized 是可重入的互斥锁,即同一个线程能够屡次取得同一把锁,而且锁的开释也只能由取得锁的线程来开释;Lock 能够是可重入的互斥锁,也能够是非可重入的互斥锁,还能够是读写锁。
  3. 锁的粒度:synchronized 是以代码块和办法为单位进行加锁和解锁,而 Lock 能够准确地管制锁的范畴,能够反对多个条件变量。
  4. 性能:在低并发的状况下,synchronized 的性能优于 Lock,因为 Lock 须要显式地获取和开释锁,而 synchronized 是在 JVM 层面实现的;在高并发的状况下,Lock 的性能可能优于 synchronized,因为 Lock 能够更好地反对高并发和读写拆散的场景。

总的来说,synchronized 的应用更加简略,然而在某些场景下会受到性能的限度;而 Lock 则更加灵便,能够更准确地管制锁的范畴和条件变量,然而应用起来比拟繁琐。须要依据具体的业务场景和性能需求来抉择应用哪种锁机制。

本文已收录至《Java 面试突击》,专一 Java 面试 100 年,查看更多:www.javacn.site

正文完
 0