目录
1. 什么是同步锁?
2. 单例模式中的懒汉式是怎么实现的?
3. 懒汉式单例模式的线程安全实现
4. 造成性能损耗的原因
5. 总结
1. 什么是同步锁?
同步锁是多线程编程中用于保护共享资源或临界区的机制,它可以确保在同一时刻只有一个线程可以访问共享资源,避免了多个线程同时访问造成的数据竞争和不一致性。
2. 单例模式中的懒汉式是怎么实现的?
懒汉式单例模式是指在第一次使用时才进行实例化,以延迟实例化的方式来节省资源。但是在多线程环境下,如果多个线程同时进入了懒汉式的实例化方法,就可能会创建多个实例,破坏了单例模式的原则。为了解决这个问题,需要使用同步锁来保证线程安全。
3. 懒汉式单例模式的线程安全实现
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 添加同步锁,确保线程安全
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
上述代码通过在 getInstance() 方法上添加 synchronized 关键字,使得在多线程环境下只有一个线程可以进入临界区,从而保证了线程安全。但是这种方式会带来性能的损耗,因为每次获取实例都需要同步锁的判断和获取,即使实例已经被创建了。
4. 造成性能损耗的原因
这种方法会造成性能损耗的主要原因是因为使用了 synchronized 关键字对整个 getInstance() 方法进行了同步化。具体来说有以下几个方面的性能损耗:
-
竞争锁资源: 在多线程环境下,每次调用 getInstance() 方法都会尝试获取同步锁。如果此时有其他线程正在使用该同步锁,那么当前线程就会进入阻塞状态,等待锁资源释放。这会导致线程在竞争锁资源上浪费时间,降低了程序的并发性能。
-
锁粒度过大: 使用 synchronized 关键字修饰整个 getInstance() 方法的方式,使得整个方法成为一个临界区,只能有一个线程进入执行,而其他线程需要等待。这样的锁粒度过大,即使是不需要同步的部分也会被阻塞,造成了不必要的性能损耗。
-
重复获取锁开销: 即使实例已经被创建了,但每次调用 getInstance() 方法时仍然需要尝试获取同步锁。这种重复获取锁的开销是不必要的,因为在实例已经被创建后,不再需要同步锁的保护。
虽然使用 synchronized 关键字确保了线程安全,但由于同步锁的获取和释放会带来性能损耗,因此在高并发场景下会影响程序的性能表现。为了提高性能,可以考虑其他线程安全的实现方式,如双重检查锁(Double-Checked Locking)、静态内部类等。
5. 总结
同步锁是多线程编程中常用的保护机制,它能够确保线程安全地访问共享资源。在单例模式中的懒汉式实现中,同步锁被广泛应用来保证在多线程环境下只创建一个实例,从而实现了线程安全的延迟实例化。通过合理地使用同步锁,可以避免线程安全问题,保证程序的正确性和稳定性。 ????️????