手撕奇偶线程交替打印1-100,3个窗口售票(防超卖)。!!!大厂最爱手撕java并发编程题

先来个单例模式压压惊,单例模式也是面试常考的哦。

饿汉式(jvm保证线程安全)

/*
饿汉式由jvm来保证一个类的<cintit>方法在多线程环境下被正确地加锁同步,如果多个线程同时去初始化一个类,
那么只会有其中一个线程去执行这个类的<cinit>方法,其他线程都需要阻塞等待,直到活动线程执行完毕。
如果一个类的<cinit>方法执行耗时太长,可能造成多个线程阻塞等待。
 */
public class SingtonHungry {
	public SingtonHungry() {
	}
	private static SingtonHungry instance=new SingtonHungry();
	public static SingtonHungry getInstance(){
		return instance;
	}
}

懒汉式1(非改进版,存在线程安全问题)

/*
如果abc三个线程同时调用静态的getInstance(),
会造成多个线程获得不同的instance实例(分配的内存地址不同),
这就有违单例模式了,所以这是有问题的。
 */
public class SingletonLazy {
	private static SingletonLazy instance=null;
	private static SingletonLazy getInstance(){
		if(instance==null){
			instance=new SingletonLazy();
		}
		return instance;
	}
}

懒汉式2(改进版,线程安全,但吞吐量太低)

/*
使用synchronized锁来保护临界区共享资源
 */
public class SingletonLazy {
	private static SingletonLazy instance=null;
	private static SingletonLazy getInstance(){
		synchronized (SingletonLazy.class) {
				/*这里是线程安全的,因为每次进来都需要加锁。
				打个比方,ab线程同时进来,a线程进入monitorEnter的逻辑,b线程进入entryList阻塞队列去等待锁释放,
				a线程初始化完instance后,进入monitorExit逻辑,释放锁。b线程还需要再次判断instance是否为null。
				 */
			if(instance==null) {
				instance = new SingletonLazy();
			}
		}
		//缺点就是,不管instance是否初始化完成,后续的每个线程进来获取instance实例都需要加锁,效率太低。
		return instance;
	}
}

懒汉式3(双重检查锁,存在线程安全问题,因为现代cpu多级指令流水线提高吞吐量的同时,可能会导致指令重排序,需要大量压测才能测试出来这个问题)

/*
双重检查锁
 */
public class SingletonLazy {
	public SingletonLazy() {
	}
	private static SingletonLazy instance=null;
	private static SingletonLazy getInstance(){
		/*
		这样看似已经做到线程安全了,并且后续线程进来只需判断instance是否为null,发现不为null直接返回即可。
		但还是存在问题的实际上。
		 */
		/*
		分析:第一重检查的instance==null的逻辑判断是没有加锁的,并且也没有使用volatile关键字来修饰。所以极端情况:
		a、b两个线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值