我知道i ++不是线程安全操作。我也明白为什么我++也比我= i + 1更快。在线程安全方面,i = i + 1与i ++有什么不同?任何字节码级别的解释都会很有帮助。就原子性而言,i ++和i = i + 1之间的区别
回答
i += 1
和i++
都不是原子的(都不是线程安全的)。 ++i
也是如此。这里有一个简单的测试,你可以运行来证明这一点:
public class Test {
static volatile int x, y;
static class IncThread extends Thread {
public void run() {
for (int i=0; i<50000; i++) x++;
for (int i=0; i<50000; i++) y = y+1;
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new IncThread();
Thread t2 = new IncThread();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.printf("x = %d, y = %d%n", x, y);
}
}
这是我得到的输出:
x = 99897, y = 81556
显然,一些写的迷路了。有一个很好的小博客文章,++ not considered atomic,解释这一点。这篇文章也指出@八月的答案是误导性的。该字节码(iinc
)仅用于增加局部变量,这从线程安全的角度来看并不令人感兴趣。 (博客文章还讨论了用于增量的不同字节码。)
如果您在8月份的回答中遇到问题,您应该在该答案下发表评论,并且可能会降低评分。有人可能会使用这个答案,甚至没有看到你的答案。 – 2014-12-02 04:35:27
还有就是,字节代码明智i++
和i += 1
之间没有差异:
增量(来源):
public static void main(String[] args) {
int i = 0;
i++;
}
增量(字节码):
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iinc 1, 1
5: return
化合物加成(来源):
public static void main(String[] args) {
int i = 0;
i += 1;
}
化合物加成(字节码):
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iinc 1, 1
5: return
用于递增字段字节码也是相同的,尽管它不使用(因为它需要一个局部变量索引):
int x;
void inc() { x++; }
void assign() { x += 1; }
void inc();
Code:
0: aload_0
1: dup
2: getfield #2 // Field x:I
5: iconst_1
6: iadd
7: putfield #2 // Field x:I
10: return
void assign();
Code:
0: aload_0
1: dup
2: getfield #2 // Field x:I
5: iconst_1
6: iadd
7: putfield #2 // Field x:I
10: return
如何从编译源代码读取字节码? – 2014-12-02 04:16:55
@DavidJones你可以使用'javap -c Foo。(或我相当蹩脚的[网站](http://bytes.i-i.im/)) – August 2014-12-02 04:18:53
酷!谢谢... – 2014-12-02 04:19:42
在这些术语中,i ++和i = i + 1没有区别。
请检查这些以了解差异http://stackoverflow.com/a/29559727/4025692 – 2015-04-10 11:17:34
i=i+1
使用一个二元运算符(+)加载i的值,并将其加1,然后将结果存回i中。相比之下,i++
使用一元(++)运算符,它使用单个汇编指令简单地增加该值,因此理论上它可能更高效。然而,今天的编译器优化i=i+1
和i++
将导致相同的优化代码。
- 1. Javascript:Forloop i ++和(i + 1)之间的区别
- 2. *(matrix1 + i)和* matrix1 [i]之间的区别?
- 3. 从任何角度来看,++ i和i + = 1之间的区别
- 4. i = i + j有什么区别;和i + = j;在C语言?
- 5. (1 << 32)和(1 << i)之间的区别其中i == 32
- 6. Increment ++ i,i ++和i + = 1
- 7. printf(“%d”,i ++)和i ++之间有什么区别;的printf( “%d”,i)的?
- 8. I/O端口和I/O内存之间的区别
- 9. * x = i和x =&i之间的区别是什么
- 10. int p = *(int *)i和int p = *(int *)&i之间的区别
- 11. 德尔福的inc(i)和i:= i + 1之间有性能差异吗?
- 12. i-vector和d-vector之间的区别
- 13. i ++和++ i有什么区别?
- 14. --i和i--有什么区别?
- 15. i == 0和0 == i有区别吗?
- 16. ++ i和i + 1在javascript中的区别是什么
- 17. 在MATLAB中使用(j,i)与(i,j)之间的区别
- 18. C中i--和i-1有什么区别?
- 19. 为什么“for($ i = 1; $ i -le 1000000; $ i ++){}”的执行时间快于“for([int] $ i = 1; $ i -le 1000000; $ i ++){}”在PowerShell中
- 20. USB标准中语法I(0,1)和I(1,0)之间的区别是什么?
- 21. 为什么i = i + 1比i ++快?
- 22. “i ++”如何比“i = i + 1”更高效?
- 23. 为什么人们使用i = i + 1而不是i ++?
- 24. 对于(我在数组中)和for(var i = 0; i <array.length; i ++)之间的区别
- 25. C#中++ i和i ++之间有任何性能差异吗?
- 26. (数组中的x)和(i = 0; i <array.length; i ++)
- 27. PHP中的++ $ i和$ i ++有什么区别?
- 28. 将i和i传递给函数的区别
- 29. C++ array.at(i)和array [i]的性能
- 30. Cypher:找到满足步骤i和i之间的条件的路径+ 1
它们编译为[相同的字节码](http://pastebin.com/raw.php?i=G6Hadz8Q),所以它们应该具有相同的性能。 – August 2014-12-02 04:03:00
@ August2 - 尼斯。您应该将其作为答案发布。 – EJK 2014-12-02 04:05:44