多线程与高并发(二)

LockSupport与synchronized对比

阻塞和释放线程时,synchronized方法使用的时 wait()notify() 方法并且需要保证synchronized、wait()、notify()方法对象必须一致,一个synchronized代码块只能有一个线程调用wait()和notify()方法。而在JDK1.6中java.util.concurrent的子包locks中引入了LockSupport这个API ,这个LockSupport是一个比较底层的工具。java锁的核心同步器框架的核心AQS:AbstractQueuedSynchronizer就是通过LockSupport.park()和LockSupport.unpark()方法来实现阻塞唤醒线程的。

public class LockSupportTEST {
	public static void main(String[] args) {
		Thread t1 = new Thread(()->{
			LockSupport.park();
			System.out.println("我是很厉害的哦");
		});
		t1.start();
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Thread t2 = new Thread(()->{
			System.out.println("都是渣渣");
			LockSupport.unpark(t1);
		});
		t2.start();
	}
}

执行结果:
执行结果
根据上面的程序来看当t1线程执行 start() 方法时,调用的LockSupport.park()方法,阻塞等待方法的执行,接下来睡2秒,此时t1线程处于阻塞状态,两秒之后t2线程执行,先输出打印内容,之后唤醒t1线程。此时t1线程打印内容。

public class LockSupportTEST {
	static Thread t1=null,t2 = null;
	public static void main(String[] args) {
		t2 = new Thread(()->{
			System.out.println("都是渣渣");
			LockSupport.unpark(t1);
		});
		t1 = new Thread(()->{
			LockSupport.park();
			System.out.println("我是很厉害的哦");
		});
		t2.start();
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t1.start();
		
	}
}

在这里插入图片描述

上面的程序t2线程先执行,优先使用LockSupport.unpak()方法,再执行t1线程的LockSupport.park()方法,结果显示t1正常输出结果。因此在阻塞之前唤醒某个线程,之后再调用阻塞方法,是可以直接通过的。

public class LockSupportTEST {
	static Thread t1=null,t2 = null;
	public static void main(String[] args) {
		t2 = new Thread(()->{
			System.out.println("都是渣渣");
			LockSupport.unpark(t1);
		});
		t1 = new Thread(()->{
			LockSupport.park();
			System.out.println("我是很厉害的哦");
			LockSupport.park();
			System.out.println("我又来了!!");
		});
		t1.start();
		t2.start();
	}
}

执行结果:
在这里插入图片描述
根据上面的程序分析:当某个线程调用两次park()方法,另外一个线程只调用了一次unpark()方法,则这个程序只会被释放到第二次阻塞之前。第二次阻塞将持续永远。

总结

  1. LockSupport不需要synchronized加锁就可以实现线程的阻塞和唤醒
  2. LockSupport.unpark()可以先于LockSupport.park()方法执行,并且线程不会阻塞。
  3. 如果一个线程处于等待状态,连续调用了两次park()方法,并且只调用了一次unpark()方法,则线程会永久处于等待状态。

LockSupport中park()和unpark()方法的实现原理

park()和unpark()方法的实现是由Unsafe类提供的,原理是通过一个变量的标识,变量值在1和0之间来回切换,当这个变量大于0的时候线程就获得了“令牌”

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页