Java中for(;;)和while(true)的区别

网友投稿 288 2022-09-12


Java中for(;;)和while(true)的区别

目录QgMsl1、问题来源2、比较2.1 测试代码for2.2 测试代码while3、结论

1、问题来源

在阅读java的JDK源码时,发现大部分写源码的大佬http://多采用for(;;)的方式来死循环,比如说AQS(AbstractQueuedSynchronizer)中大量使用的自旋的方式获取共享状态。

/**

* 通过“死循环”的方式来正确的添加节点

*/

private Node enq(final Node node) {

// 不断循环,直至CAS插入节点成功

for (;;) {

Node t = tail;

if (t == null) {

// 当尾节点为null,此时需要初始化头节点和尾节点

http:// if (compareAndSetHead(new Node()))

tail = head;

} else {

// 插入节点前驱节点指向原先尾节点

node.prev = t;

// CAS插入至同步队列的尾节点

if (compareAndSetTail(t, node)) {

t.next = node;

return t;

}

}

}

}

/**

* “死循环”获取同步状态,并且当前仅当前驱节点是头节点是才能够尝试获取同步状态

*/

final boolean acquireQueued(final Node node, int arg) {

boolean failed = true;

try {

boolean interrupted = false;

// 不断循环

for (;;) {

// 获取当前节点的前驱节点,如果前驱节点为null将会抛出空指针异常

final Node p = node.predecessor();

// 如果当前节点的前驱节点是头节点,尝试获取同步状态

if (p == head && tryAcquire(arg)) {

// 设置当前节点为头节点,并且将节点线程和节点的前驱节点置为null,help GC

setHead(node);

p.next = null; // help GC

failed = false;

return interrupted;

}

// 如果不符合条件,则判断当前节点前驱节点的waitStatus状态来决定是否需要挂起LockSupport.park(this);

if (shouldParkAfterFailedAcquire(p, node) &&

parkAndCheckInterrupt())

interrupted = true;

}

} finally {

// 失败则取消

if (failed)

cancelAcquire(node);

}

}

2、比较

Java代码在编译后都会装换为虚拟机可以识别的字节码,我们通过编译器对两者生成的字节码从原理是来观察两者的区别

2.1 测试代码for

package com.liziba.jsw;

/**

*

* for死循环测试

*

*

* @Author: Liziba

* @Date: 2021/6/21 11:36

*/

public class Test {

private static void m1() {

for (;;) {

}

}

}

通过 javap -v Test.class查看生成的字节码(只截取关键部分)

2.2 测试代码while

package com.liziba.jsw;

/**

*

* while死循环测试

*

*

* @Author: Liziba

* @Date: 2021/6/21 11:36

*/

public class Test {

private static void m2() {

while (true){

}

}

}

通过 javap -v Test.class查看生成的字节码(只截取关键部分)

3、结论

for死循环和while死循环编译后的字节码(编译器是可以做优化的),完全一模一样,所以两者在使用过程中,其实是没有任何区别。看到这里是不是有点生气,但是又想问问什么源码那些大佬写代码基本上不用while(true),我想主要原因还是早期C语言中for(;;)循环和while(1)编译生成的字节码不一样,for(;;)生成的字节码明显更加少,一定程度上能节省一些内存空间。所以很多java大佬,也是精通各种其他语言的,因此写法习惯也就延续下来了吧。再者,我在查阅资料的时候也看到有笔者验证早期的Java编译器对for死循环编译生成的字节码也是少于while死循环编译后生成的字节码,可能随着编译器优化能力不断的增强,现在这两者在目前广泛使用的编译器中已经没有什么区别了。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:网络分流器-网络分流器-网络安全评估探讨(网络分流器厂家)
下一篇:net-snmp 支持ipv6(net-snmp安装)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~