知乎视频解释:网络传输原理:什么是TCP滑动窗口

传统课本上单例模式分两种,一种饿汉式,一种懒汉式。对应的代码如下:
详解双重饿汉模式和懒汉模式:单例模式中的懒汉模式,饿汉模式 , 双检锁/双重校验锁
public class Singleton {
private static Singleton instance = new Singleton(); // 在类加载的时候就会实例化
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
饿汉式在类加载时就实例化对了,使用时直接调用 getInstance() 方法。这个模式为线程安全的,在多线程并发模式下不会重复实例化对象。
优点: 效率高 缺点: 对象实例化过早,浪费内存资源
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
这种模式没有在加载时实例化对象,而是在调用getInstance() 方法时实例化对象,使用懒汉式是为了避免过早的实例化,减少内存资源浪费。
优点:第一次调用才初始化,避免内存浪费。 缺点: 只适合单线程,线程不安全
参考:用单例模式来讲讲线程安全
双检锁/双重校验锁(DCL,即 double-checked locking)
参考:双检锁/双重校验锁(DCL,即 double-checked locking)详细解析
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();//erro
}
}
}
return instance;
}
public static void main(String[] args) {
Singleton.getInstance();
}
}
public static Singleton getInstance() {
if (instance == null) {//线程1,2同时到达,均通过(instance == null)判断。
// 线程1进入下面的同步块,线程2被阻塞
synchronized (Singleton.class) {
if (instance == null) {//线程1执行发现instance为null,初始化实例后,释放锁。
// 线程2进入同步块,此次instance已经被初始化。无法通过if条件,避免多次重复初始化。
instance = new Singleton();
}
}
}
return instance;
}
执行双重检测是因为,如果多个线程通过了第一次检测,此时因为synchronized,其中一个线程会首先通过了第二次检测并实例化了对象,剩余的线程不会再重复实例化对象。这样,除了初始化的时候会加锁,后续的调用都是直接返回,解决了多余的性能消耗。
if (instance == null) {
instance = new Singleton();//erro
}
如果不使用volatile关键字,隐患来自于上述代码中注释了 erro 的一行,这行代码大致有以下三个步骤:
由于 Java 内存模型允许“无序写入”,有些编译器因为性能原因,可能会把上述步骤中的 2 和 3 进行重排序,顺序就成了
