V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twogoods
V2EX  ›  Java

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

  •  
  •   twogoods · 2017-04-22 14:35:34 +08:00 · 2660 次点击
    这是一个创建于 2773 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    正确的 java benchmark 要用 JMH 这种套件来做,它包含了预热和防止代码被 DCE 。在正确使用 JMH 的时候,你就可以得到一个正确的 benchmark 结果了
    0915240
        6
    0915240  
       2017-04-22 17:02:52 +08:00
    既然是要获取基准测试并且感知到小差距,建议换到用 jmh 试试看。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3006 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:58 · PVG 20:58 · LAX 04:58 · JFK 07:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.