Java并发——LockSupport、Condition解析
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java并发——LockSupport、Condition解析,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4723字,纯文字阅读大概需要7分钟。
内容图文
![Java并发——LockSupport、Condition解析](/upload/InfoBanner/zyjiaocheng/845/5725ccf82f6648f7ac2ae13c67163954.jpg)
LockSupport
LockSupport
类是一个工具类,用来在显示锁里面替换Object
类的wait
、notify
方法的。在内置锁里面,wait
方法必须在线程持有锁的时候才能对线程进行阻塞,但是LockSupport
类却不一样,即使线程没有持有锁,它也能将该线程阻塞,它有两个重要的方法,但是底层的实现是由Unsafe
类来实现的,也就是说,是由JVM来实现的:
public static void park() {
UNSAFE.park(false, 0L);
}
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
park
方法是阻塞线程,而unpark
方法是唤醒被park
方法阻塞的线程,如下代码:
public class Test {
public static void main (String args[]) throws InterruptedException {
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("蕾姆被障碍挡住啦");
LockSupport.park();
System.out.println("拉姆帮蕾姆清扫了障碍");
}
});
thread.start();
Thread.sleep(3000);
System.out.println("三秒后拉姆来帮蕾姆清扫障碍了");
LockSupport.unpark(thread);
}
}
//打印:
//蕾姆被障碍挡住啦
//三秒后拉姆来帮蕾姆清扫障碍了
//拉姆帮蕾姆清扫了障碍
从代码结果看出LockSupport
阻塞了线程,三秒后由unpark
方法唤醒接着运行。LockSupport
阻塞线程的实质是以唯一一个许可证来完成的,unpark
方法是给线程一个许可,而park
方法是回收线程的许可,如果没有许可则陷入阻塞,不管调用几个unpark
方法,线程中的许可始终只有一个。出于这个特性,unpark
方法甚至可以在park
方法之前调用。还有一点与wait
方法不同,它阻塞的时候不会释放锁:
public static void main (String args[]) throws InterruptedException {
Lock lock=new ReentrantLock();
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println("蕾姆被障碍挡住啦");
LockSupport.park();
System.out.println("拉姆帮蕾姆清扫了障碍");
lock.unlock();
}
});
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println("拉姆来帮蕾姆清扫障碍了");
LockSupport.unpark(thread);
lock.unlock();
}
});
thread.start();
thread1.start();
//只输出:蕾姆被障碍挡住啦
输出完蕾姆被障碍挡住啦
后,两个线程都陷入阻塞的状态,可见,确实没有释放掉锁。
Condition
Condition
在Java中是用于多线程协调通信的工具类,一般用于显示锁,即ReetrantLock
的通信,与LockSupport
类一样,提供了await
方法、signal
方法以及signalAll
方法对应,Object
类的wait
、notify
、notifyAll
方法。以下面的代码为例:
public class Test {
public static void main (String args[]) throws InterruptedException {
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println("蕾姆被障碍挡住啦");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("拉姆帮蕾姆清扫了障碍");
lock.unlock();
}
});
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println("拉姆来帮蕾姆清扫障碍了");
condition.signal();
lock.unlock();
}
});
thread.start();
thread1.start();
}
}
//输出:
//蕾姆被障碍挡住啦
//拉姆来帮蕾姆清扫障碍了
//拉姆帮蕾姆清扫了障碍
Condition
的创建时依赖于ReentrantLock
可重入锁的,因为Condition本质是一个接口,它的实现交由AQS框架
完成的,如果对AQS框架不熟的同学可以看看这篇文章:Java并发——AQS框架详解。从上述例子中可以看出,它与Object类的wait方法一样是在阻塞的过程中释放锁的。在AbstractQueuedSynchronizer
类中可以找到await
方法源码:
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//d对当前线程包装,设置为CONDITION状态
Node node = addConditionWaiter();
//释放当前线程占有的锁
int savedState = fullyRelease(node);
int interruptMode = 0;
//释放完毕后,遍历AQS的队列,看当前节点是否在队列中,
// 不在说明它还没有竞争锁的资格,所以继续将自己沉睡。
// 直到它被加入到队列中,signal时加入同步队列
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
//检查是否正在阻塞
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//等待重新加入同步队列,请求资源
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
AQS框架
维护了一个同步队列,当持有锁的线程调用await
方法时,AQS
会把这个等待被唤醒的线程移除该队列,并调用LockSupport
类的park
方法使其陷入阻塞。当调用signal
方法时,会把该线程重新加入同步队列,与其它线程抢夺资源。signal
方法源码如下:
public final void signal() {
//判断是否是独占锁
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//唤醒第一个等待队列的线程
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
signal
方法与notify
方法不同,它总是唤醒第一个处于等待队列中的线程,而notify
是随机的唤醒处于等待队列中的线程。doSignal
方法底层调用了transferForSignal
方法,该方法让处于CONDITION状态
的线程,变为0状态
并使其从等待队列中加入同步队列,去重新和其它线程竞争,且调用unpark方
让线程恢复运行,signalAll
原理一样。
内容总结
以上是互联网集市为您收集整理的Java并发——LockSupport、Condition解析全部内容,希望文章能够帮你解决Java并发——LockSupport、Condition解析所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。