简述
简单一句话:synchronize 关键字用于在 Java 中实现线程同步。
线程同步:线程同步是指控制多个线程访问共享资源的行为,确保在任意时刻只有一个线程可以访问共享资源,以避免数据不一致或竞态条件等问题。
在 Java 中,多线程环境下的线程同步可以通过 synchronize 关键字来实现,当一个方法或代码块被 synchronize 修饰时,它就成为了一个同步方法或同步代码块,同一时间只有一个线程可以执行其中的代码,其他线程需要等待执行。
synchronize 关键字的作用:
- 确保原子性操作
对于一些需要原子性操作的代码段,通过synchronize关键字可以确保整个操作在同一时间只被一个线程执行,避免了线程之间的干扰。
- 保护共享资源
当多个线程需要访问共享资源时,通过同步机制可以确保在任意时刻只有一个线程可以修改该资源,从而避免了数据的不一致性。
- 避免竞态条件
通过限制对共享资源的访问,可以避免竞态条件的发生,确保线程执行的可靠性和一致性。
使用方法
- 同步实例方法
使用 synchronized 修饰普通的实例方法,确保同一时间只有一个线程可以访问该实例方法,锁定的是当前实例对象。
public class SynchronizeInstance {
public synchronized void synchronizedInstanceMethod() {
// 同步实例方法的代码
}
}
- 同步代码块
使用 synchronized 关键字将代码块包裹起来,确保同一时间只有一个线程可以执行该代码块,可以选择性地指定锁定的对象。
public class SynchronizeInstance {
public void synchronizedStaticMethod() {
synchronized (lockObject) {
// 同步代码块的代码
}
}
}
- 同步静态方法
使用 synchronized 修饰静态方法,确保同一时间只有一个线程可以访问该静态方法,锁定的是类的 SynchronizeInstanceClass 对象。
public class SynchronizeInstanceClass {
public static synchronized void synchronizedStaticMethod() {
// 静态同步方法的代码
}
}
实践 - 双重校验锁
使用单例模式和 synchronized 关键字实现一个双重校验锁
public class Singleton {
private static volatile Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
// 第一重校验,提高代码效率,如果已经实例化了则会直接返回
if (INSTANCE == null) {
synchronized (Singleton.class){
/*
* 第二重校验,这里作个假设:有两个线程T1,T2
* 当T1进入了第一重校验,准备争抢资源时,T2先获取到了资源
* 此时INSTANCE == null是成立的,故T2进行了实例化,并释放了资源
* T1获取到了资源,它并不知道T2是否已经实例化了对象
* 所以需要进行第二重校验,确保只有一个实例被创建
*/
if (INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}