java的LockSupport

LockSupport简介

位于java.util.concurrent.locks包下,线程的阻塞原语,用来阻塞线程和唤醒线程,每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在线程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。

方法介绍

阻塞线程

  1. void park():阻塞当前线程,如果调用unpark方法或者当前线程被中断,从能从park()方法中返回
  2. void park(Object blocker):功能同方法1,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
  3. void parkNanos(long nanos):阻塞当前线程,最长不超过nanos纳秒,增加了超时返回的特性;
  4. void parkNanos(Object blocker, long nanos):功能同方法3,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
  5. void parkUntil(long deadline):阻塞当前线程,直到deadline(时间戳);
  6. void parkUntil(Object blocker, long deadline):功能同方法5,入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;

唤醒线程

void unpark(Thread thread):唤醒处于阻塞状态的指定线程。

LockSupport的pack()、unpack()与Thread的wait()、notify()的区别

主要的区别应该说是它们面向的对象不同。阻塞和唤醒是对于线程来说的,LockSupport的park/unpark更符合这个语义,以“线程”作为方法的参数, 语义更清晰,使用起来也更方便。而wait/notify的实现使得“阻塞/唤醒对线程本身来说是被动的,要准确的控制哪个线程、什么时候阻塞/唤醒很困难, 要不随机唤醒一个线程(notify)要不唤醒所有的(notifyAll)。每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在线程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。

Lock和LockSupport的联系

Lock是ReentrantLock之类的显式锁,都是基于AQS实现的,而AQS的底层都是基于LockSupport实现的。

sleep、wait、park、Condition这几个线程等待操作的比较

实现原理(底层)

sleep:native 方法,内核定时器触发
wait:native 方法,配合 synchronized 的 monitorenter 和 monitorexit 指令
park:native 方法,二元信号量
Condition:AQS 维护等待队列与同步队列

编码操作

sleep:Thread.sleep 静态方法
wait:使用 synchronized 加锁的对象,Object 的 wait/notify
park:LockSupport.park/unpark
Condition:由 Lock 对象 newCondition 方法创建,wait/signal

等待时是否释放锁

sleep:不释放
wait:释放
park:释放
Condition:释放

超时等待

sleep:支持
wait:支持
park:支持
Condition:支持

等待过程中断

sleep:支持
wait:支持
park:支持
Condition:支持

唤醒操作

sleep:不支持,定时器唤醒
wait:支持,notify/notifyAll
park:支持,unpark
Condition:支持,signal/signalAll

等待操作精准性

sleep:当前线程
wait:当前线程
park:指定具体的线程
Condition:当前线程

唤醒操作精准性

wait:notify 随机唤醒一个线程,notifyAll 唤醒所有等待的线程
park:unpark 唤醒指定的线程
Condition:signal 随机唤醒一个线程,signalAll 唤醒所有等待的线程

执行顺序

park:unpark 可以在 park 前执行。可以先调用 unpark 方法释放一个许可证,后面线程调用 park 方法时,发现已经许可证了,就可以直接获取许可证而不用进入休眠状态了
wait/notify:保证 wait 方法比 notify 方法先执行。如果 notify 方法比 wait 方法晚执行的话,就会导致因 wait 方法进入休眠的线程接收不到唤醒通知的问题
Condition:保证 wait 方法比 signal 方法先执行。

发布了196 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/fall_hat/article/details/104653341