谁帮忙看看这段 Java 并发代码

2017-04-22 14:35:34 +08:00
 twogoods

我开了 100 个线程用同一个 id 分别去请求这两个方法,把这 100 次方法执行时间的平均值取出来,并且相同的方法重复做了三次得到结果: a: 24907.9ms, b: 24831.1ms ,看结果方法 b 好一点,但这个差距是不是很小啊?

@Controller
@RequestMapping("/bench/")
public class BenchController {

    private static Object[] lockObj;
    private static AtomicReference<Integer>[] locks;
    static {
        lockObj = new Object[100];
        for (int i = 0; i < lockObj.length; i++) {
            lockObj[i] = new Object();
        }

        locks = new AtomicReference[100];
        for (int i = 0; i < locks.length; i++) {
            locks[i] = new AtomicReference<Integer>(null);
        }
    }

    @RequestMapping("a")
    @ResponseBody
    public long a(int id) throws Exception {
        long start = System.currentTimeMillis();
        int index = id % 100;
        synchronized (lockObj[index]) {
            Thread.sleep(500);
        }
        long result=System.currentTimeMillis() - start;
        System.out.println(result);
        return result;
    }

    @RequestMapping("b")
    @ResponseBody
    public long b(int id) throws Exception {
        long start = System.currentTimeMillis();
        int index = id % 100;
        while (!locks[index].compareAndSet(null, id)) {
        }
        Thread.sleep(500);
        locks[index].compareAndSet(id, null);
        long result=System.currentTimeMillis() - start;
        System.out.println(result);
        return result;
    }
}

2654 次点击
所在节点    Java
6 条回复
sorra
2017-04-22 14:44:43 +08:00
sleep 是有误差的,你的测试可能是无效的。可以在方法内循环大量次数来测试,也许能有效果
sagaxu
2017-04-22 14:59:09 +08:00
sleep 一下要 500ms , lock 一下是不到 1ms 的, sleep 本身的误差已经远大于 lock 的开销。结论,这测试就是胡乱测的。 JVM 的 jit 预热,这里更加看不到了。
twogoods
2017-04-22 15:21:40 +08:00
@sagaxu 确实是自己瞎搞的😂,就是想看看有锁与无锁的差别有多大,求指导
Ouyangan
2017-04-22 15:22:57 +08:00
二楼的说法靠谱
记得 JDK1.6 的 JIT C2 策略阈值是 10000 , 楼主可以先在静态代码块中先跑个 10000 次 ,触发 JIT 后再做比较 .

推荐补补 JVM 类执行机制的知识
hyperdak
2017-04-22 15:31:45 +08:00
micro benchmark 会被 gc 、 jit 、不正确的代码影响,你得到结果本身就是错的。

正确的 java benchmark 要用 JMH 这种套件来做,它包含了预热和防止代码被 DCE 。在正确使用 JMH 的时候,你就可以得到一个正确的 benchmark 结果了
0915240
2017-04-22 17:02:52 +08:00
既然是要获取基准测试并且感知到小差距,建议换到用 jmh 试试看。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/356628

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX