Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java volatile int比AtomicInteger快吗_Java - Fatal编程技术网

Java volatile int比AtomicInteger快吗

Java volatile int比AtomicInteger快吗,java,Java,我正在做一个示例练习,我发现一个奇怪的观察结果,如果我用volatile替换AutomicInteger,程序运行速度会更快。注意:我只做读取操作 代码: import java.util.ArrayList; 导入java.util.List; 导入java.util.concurrent.AtomicInteger; 公共班机{ AtomicInteger=新的AtomicInteger(100000000); //易失整数=100000000; 公共静态void main(字符串[]arg

我正在做一个示例练习,我发现一个奇怪的观察结果,如果我用volatile替换AutomicInteger,程序运行速度会更快。注意:我只做读取操作

代码:

import java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.AtomicInteger;
公共班机{
AtomicInteger=新的AtomicInteger(100000000);
//易失整数=100000000;
公共静态void main(字符串[]args){
//我们将存储线程,以便检查它们是否完成
List threads=new ArrayList();
长启动=System.currentTimeMillis();
Main Main=新Main();
//我们将创建500个线程
对于(int i=0;i<500;i++){
Runnable task=newmyrunnable(main.integer);
线程工作者=新线程(任务);
//我们可以设置线程的名称
worker.setName(String.valueOf(i));
//启动线程,不要直接调用run()方法
worker.start();
//记住线程以便以后使用
线程。添加(worker);
}
int运行=0;
做{
运行=0;
用于(线程:线程){
if(thread.isAlive()){
运行++;
}
}
System.out.println(“我们有“+running+”running threads.”);
}同时(运行>0);
System.out.println(“所需总时间:”+(System.currentTimeMillis()-start));
}
} 
MyRunnable类:

 import java.util.concurrent.atomic.AtomicInteger;

public class MyRunnable implements Runnable {
private final AtomicInteger countUntil;

MyRunnable(AtomicInteger countUntil) {
    this.countUntil = countUntil;
}

@Override
public void run() {
    long sum = 0;
    for (long i = 1; i < countUntil.intValue(); i++) {
        sum += i;
    }
    System.out.println(sum);
}
}
导入java.util.concurrent.AtomicInteger;
公共类MyRunnable实现Runnable{
私有最终原子整数countUntil;
MyRunnable(原子整数countUntil){
this.countUntil=countUntil;
}
@凌驾
公开募捐{
长和=0;
for(长i=1;i
在我的计算机上使用AutomicInteger运行此程序所需的时间

所需总时间:102169

所需总时间:90375

在我的计算机上使用volatile运行此程序所需的时间

所需总时间:66760

所需总时间:71773


这是否意味着volatile在读取操作方面也比AutomicInteger快?

这个问题取决于特定的JVM、硬件和操作系统,因此唯一可能的答案是“可能”。

在读取上下文中,AtomicInteger
基本上是围绕着
volatile int
的薄型包装器:

private volatile int value;

public final int get() {
    return value;
}

public int intValue() {
    return get();
}
不要期望包装比单独使用包装值更快。如果JVM使用内联,它的速度只能与
volatile int
一样快


提示:如果您“只执行读取操作”,则速度会更快:

static final int integer= 100000000;

如果很少有应用程序注意到这一点,那么volatile int可能比AtomicInteger更快。不过,AtomicInteger提供了更广泛的潜在用途

volatile int比AtomicInteger快吗

原子的访问和更新的内存效应通常遵循挥发物的规则,如Java中所述™ 语言规范。以下是volatile int与原子类型的比较

  • get具有读取易失性变量的记忆效果

  • set具有写入(赋值)易失性变量的记忆效果

  • lazySet具有写入(分配)易失性变量的内存效应,但它允许使用后续(但不是以前)内存操作进行重新排序,这些操作本身不会对普通非易失性写入施加重新排序约束。在其他使用上下文中,lazySet可能在为垃圾收集而清空一个永远不会被访问的引用时应用

  • weakCompareAndSet以原子方式读取和有条件地写入变量,但不会在排序之前创建任何事件,因此对于除weakCompareAndSet目标之外的任何变量的先前或后续读取和写入均不提供任何保证

  • compareAndSet和所有其他读取和更新操作(如Get和Increment)都具有读取和写入易失性变量的内存效应


如果您只执行读取操作,为什么需要担心同步问题/@thinkstipe,正如我提到的,这只是一个示例练习。令我惊讶的是,即使执行读取操作,也会出现时间差。
AtomicInteger
的存在使得对整数执行复合原子操作变得很容易,例如
addAndGet
getAndAdd
getAndSet
,等等。如果您不需要这些操作,那么您应该坚持使用
volatile int
,因为正如托马斯兹·努尔基维茨在他的回答中所解释的那样,
原子整数
是在
volatile int
之上实现的。我创建了自定义包装器来验证,是的,这就是原因。@AmitDeshpande:所以您得到的计时与
原子整数
?你能分享你的microbenchmark结果吗?第一次运行1:所需总时间:93059第二次运行:所需总时间:80608
static final int integer= 100000000;