共计 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 次要的区别有以下几个方面:
- 锁的获取形式:synchronized 是隐式获取锁的,即在进入 synchronized 代码块或办法时主动获取锁,退出时主动开释锁;而 Lock 须要程序显式地获取锁和开释锁,即须要调用 lock() 办法获取锁,调用 unlock() 办法开释锁。
- 锁的性质:synchronized 是可重入的互斥锁,即同一个线程能够屡次取得同一把锁,而且锁的开释也只能由取得锁的线程来开释;Lock 能够是可重入的互斥锁,也能够是非可重入的互斥锁,还能够是读写锁。
- 锁的粒度:synchronized 是以代码块和办法为单位进行加锁和解锁,而 Lock 能够准确地管制锁的范畴,能够反对多个条件变量。
- 性能:在低并发的状况下,synchronized 的性能优于 Lock,因为 Lock 须要显式地获取和开释锁,而 synchronized 是在 JVM 层面实现的;在高并发的状况下,Lock 的性能可能优于 synchronized,因为 Lock 能够更好地反对高并发和读写拆散的场景。
总的来说,synchronized 的应用更加简略,然而在某些场景下会受到性能的限度;而 Lock 则更加灵便,能够更准确地管制锁的范畴和条件变量,然而应用起来比拟繁琐。须要依据具体的业务场景和性能需求来抉择应用哪种锁机制。
本文已收录至《Java 面试突击》,专一 Java 面试 100 年,查看更多:www.javacn.site