Java for循环中是否有针对线程安全性的优化? [英] Is there any optimization for thread safety in for loop of Java?

查看:1217
本文介绍了Java for循环中是否有针对线程安全性的优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码,可以在两个线程中更改一个计数器.它不是线程安全的,因为我没有在代码中放置任何原子变量或锁.如果代码只运行一次,它会给出正确的结果,但是我想运行几次,因此将代码放入for循环中.问题是只有前两个循环会生成我期望的结果.对于其余的循环,结果始终为0,这似乎是线程安全的. Java虚拟机中是否有任何内部运算符导致这种情况?

I have a snippet of code that change a counter in two threads. It's not thread safe because I didn't put any atomic variable or lock in the code. It gives the right result as I expected if the code only run once, but I want to run it for several times, so I put the code into a for loop. And the question is that only the first or the first two loops will generate the result I expect. For the rest of the loops, the results are always 0, which seems to be thread safe. Is there any inner operator in Java Virtual Machine resulting such thing?

我尝试更改循环数,而第一个或第二个总是我所期望的,但是无论有多少个循环,其他两个都为0.

I have tried change the number of loops, and the first one or two are always what I expect, but the others are 0 no matter how many loops there are.

计数器:

private static class Counter {
    private int count;

    public void increase() {
        count++;
    }

    public void decrease() {
        count--;
    }

    public int getCount() {
        return count;
    }
}

人员:

// This is just a thread to increase and decrease the counter for many times.
private static class Person extends Thread {
    private Counter c;

    public Person(Counter c) {
        this.c = c;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            c.increase();
            c.decrease();
        }
    }
}

主要方法:

public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        Counter c = new Counter();
        Person p1 = new Person(c);
        Person p2 = new Person(c);
        p1.start();
        p2.start();
        p1.join();
        p2.join();
        System.out.println("run "+i+": "+c.getCount());        
   }
}

输出:

run 0: 243
run 1: 12
run 2: 0
run 3: 0
run 4: 0
run 5: 0
run 6: 0
run 7: 0
run 8: 0
run 9: 0

我不知道为什么其余结果总是为0.但是我想这与JVM的优化有关.在完成某些循环后,JVM优化代码,并忽略其余循环并始终给出0作为答案,对吗?

I don't know why the rest of the results are always 0. But I guess it's about the optimization of JVM. Is it right that the JVM optimizes the code when some loops have been done, and it omits the rest loops and always gives 0 as answer?

推荐答案

我认为JVM正在像您所说的那样在这里进行优化.

I think the JVM is optimizing here like you said.

我在您的问题中添加了一些带有时间的输出,这些输出清楚地表明优化在那里发生.

I added some outputs with timings to your question, which clearly show, that optimization happens there.

public static void main(String[] args) throws InterruptedException {

    for (int i = 0; i < 10; i++) {
        final long startTime = System.currentTimeMillis();
        Counter c = new Counter();
        Person p1 = new Person(c);
        Person p2 = new Person(c);
        p1.start();
        p2.start();
        p1.join();
        p2.join();
        final long endTime = System.currentTimeMillis();
        System.out.println(String.format("run %s: %s (%s ms)", i, c.getCount(), endTime - startTime));        
   }
}

结果:

run 0: 1107 (8 ms)
run 1: 1 (1 ms)
run 2: 0 (2 ms)
run 3: 0 (0 ms)
run 4: 0 (0 ms)
run 5: 0 (0 ms)
run 6: 0 (1 ms)
run 7: 0 (0 ms)
run 8: 0 (0 ms)
run 9: 0 (0 ms)

程序的第一次迭代需要很多时间,而在以后的执行中几乎没有时间被使用.

The first iterations the program needs a lot of time, wheras in later execution nearly no time at all is used.

似乎有理由怀疑这种行为的最佳化.

Seems to be legit to suspect optimazation for this behaviour.

使用volatile int count:

run 0: 8680 (15 ms)
run 1: 6943 (12 ms)
run 2: 446 (7 ms)
run 3: -398 (7 ms)
run 4: 431 (8 ms)
run 5: -5489 (6 ms)
run 6: 237 (7 ms)
run 7: 122 (7 ms)
run 8: -87 (7 ms)
run 9: 112 (7 ms)

这篇关于Java for循环中是否有针对线程安全性的优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆