LockSupport使用
1.简介#
在JDK1.6中的java.util.concurrent的子包locks中引了LockSupport这个API,LockSupport是一个比较底层的工具类,用来创建锁和其他同步工具类的基本线程阻塞原语。java锁和同步器框架的核心 AQS: AbstractQueuedSynchronizer,就是通过调用 LockSupport .park()和 LockSupport .unpark()的方法,来实现线程的阻塞和唤醒的。
2.使用#
-
示例1
public class TestLockSupport { public static void main(String[] args) { //使用lombda表达式创建一个线程t Thread t = new Thread(() -> { for (int i = 0; i < 10; i++) { System.out.println(i); if (i == 5) { //使用LockSupport的park()方法阻塞当前线程t LockSupport.park(); } try { //使当前线程t休眠1秒 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); //启动当前线程t t.start(); //唤醒线程t,这行代码实际运行过程中会比上面的park()方法先执行,但是线程t没有被阻塞,由此可以看出LockSupport的unpark()方法可以先于LockSupport的park()方法执行 LockSupport.unpark(t); } }
-
示例2
public class TestLockSupport { public static void main(String[] args) { //使用lombda表达式创建一个线程t Thread t = new Thread(() -> { for (int i = 0; i < 10; i++) { System.out.println(i); if (i == 5) { //调用LockSupport的park()方法阻塞当前线程t LockSupport.park(); } if (i == 8) { //调用LockSupport的park()方法阻塞当前线程t,虽然在主线程中调用了unpark方法,但是由于在i==5的时候调用过park方法,此时这里还是会阻塞 LockSupport.park(); } try { //使当前线程t休眠1秒 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); //启动当前线程t t.start(); //唤醒线程t LockSupport.unpark(t); } }
-
总结
1.LockSupport不需要synchornized加锁就可以实现线程的阻塞和唤醒
2.LockSupport.unpartk()可以先于LockSupport.park()执行,并且线程不会阻塞
3.如果一个线程处于等待状态,连续调用了两次park()方法,就会使该线程永远无法被唤醒
3.底层实现#
park()和unpark()方法的实现是由Unsefa类提供的,而Unsefa类是由C和C++语言完成的,其实原理也是比较好理解的,它主要通过一个变量作为一个标识,变量值在0,1之间来回切换,当这个变量大于0的时候线程就获得了“令牌”,从这一点我们不难知道,其实park()和unpark()方法就是在改变这个变量的值,来达到线程的阻塞和唤醒的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构