简体   繁体   English

同步的java代码执行速度比非同步代码快

[英]Synchronized java code performs times faster than unsynchronized one

I work on a high concurrency app. 我在一个高并发应用程序上工作。 In the app code I try to avoid synchronization where possible. 在应用程序代码中,我尝试尽可能避免同步。 Recently, when comparing test performance of a unsynchronized and synchronized code versions, it turned out synchronized code performed three-four times faster than its unsynchronized counterpart. 最近,在比较非同步和同步代码版本的测试性能时,结果表明同步代码的执行速度比非同步代码快三到四倍。

After some experiments I came to this test code: 经过一些实验,我来到了这个测试代码:

private static final Random RND = new Random();
private static final int NUM_OF_THREADS = 3;
private static final int NUM_OF_ITR = 3;
private static final int MONKEY_WORKLOAD = 50000;

static final AtomicInteger lock = new AtomicInteger();

private static void syncLockTest(boolean sync) {
    System.out.println("syncLockTest, sync=" + sync);

    final AtomicLong jobsDone = new AtomicLong();
    final AtomicBoolean stop = new AtomicBoolean();

    for (int i = 0; i < NUM_OF_THREADS; i++) {
        Runnable runner;

        if (sync) {
            runner = new Runnable() {
                @Override
                public void run() {
                    while (!stop.get()){
                        jobsDone.incrementAndGet();

                        synchronized (lock) {
                            monkeyJob();
                        }

                        Thread.yield();
                    }
                }
            };
        } else {
            runner = new Runnable() {
                @Override
                public void run() {
                    while (!stop.get()){
                        jobsDone.incrementAndGet();

                        monkeyJob();

                        Thread.yield();
                    }
                }
            };
        }

        new Thread(runner).start();
    }

    long printTime = System.currentTimeMillis();

    for (int i = 0; i < NUM_OF_ITR;) {
        long now = System.currentTimeMillis();
        if (now - printTime > 10 * 1000) {
            printTime = now;
            System.out.println("Jobs done\t" + jobsDone);
            jobsDone.set(0);
            i++;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    stop.set(true);
}

private static double[] monkeyJob() {
    double[] res = new double[MONKEY_WORKLOAD];
    for (int i = 0; i < res.length; i++) {
        res[i] = RND.nextDouble();
        res[i] = 1./(1. + res[i]);
    }
    return res;
}

I played with the number of threads, workload, test iterations - each time synchronized code perfomed much faster than unsunchronized one. 我玩了线程,工作负载,测试迭代次数 - 每次同步代码的执行速度比非中心代码快得多。

Here are results for two different values of NUM_OF_THREADS 以下是NUM_OF_THREADS的两个不同值的结果

Number of threads:3 线程数:3
syncLockTest, sync=true syncLockTest,sync = true
Jobs done 5951 乔布斯做了5951
Jobs done 5958 乔布斯做了5958
Jobs done 5878 乔布斯完成5878
syncLockTest, sync=false syncLockTest,sync = false
Jobs done 1399 乔布斯做了1399
Jobs done 1397 乔布斯做了1397
Jobs done 1391 乔布斯做了1391

Number of threads:5 线程数:5
syncLockTest, sync=true syncLockTest,sync = true
Jobs done 5895 乔布斯完成5895
Jobs done 6464 乔布斯完成6464
Jobs done 5886 乔布斯完成5886
syncLockTest, sync=false syncLockTest,sync = false
Jobs done 1179 工作完成1179
Jobs done 1260 乔布斯做了1260
Jobs done 1226 乔布斯做了1226

Test environment Windows 7 Professional Java Version 7.0 测试环境Windows 7 Professional Java版本7.0

Here's a simillar case Synchronized code performs faster than unsynchronized one 这是一个类似的案例同步代码比非同步代码执行得更快

Any ideas? 有任何想法吗?

Random is a thread-safe class. Random是一个线程安全的类。 you are most likely avoiding contention on calls into the Random class by synchronizing around the main job. 你最有可能通过在主要作业周围同步来避免对Random类调用的争用。

This is fascinating. 这很有趣。 I think @jtahlborn nailed it. 我想@jtahlborn坚持了它。 If I move the Random and make it local to the thread, the times for the non-sync jump ~10x while the synchronized ones don't change: 如果我移动Random并使其成为线程的本地,非同步跳转的时间约为10x而synchronized的时间不会改变:

Here are my times with a static Random RND : 以下是static Random RND

syncLockTest, sync=true
Jobs done   8800
Jobs done   8839
Jobs done   8896
syncLockTest, sync=false
Jobs done   1401
Jobs done   1381
Jobs done   1423

Here are my times with a Random rnd local variable per thread: 以下是每个线程的Random rnd局部变量的时间:

syncLockTest, sync=true
Jobs done   8846
Jobs done   8861
Jobs done   8866
syncLockTest, sync=false
Jobs done   25956   << much faster
Jobs done   26065   << much faster
Jobs done   26021   << much faster

I also wondered if this was GC related but moving the double[] res to being a thread local did not help the speeds at all. 我也想知道这是否与GC相关,但将double[] res移动到本地线程并没有帮助速度。 Here's the code I used: 这是我使用的代码:

...
@Override
public void run() {
    // made this be a thread local but it affected the times only slightly
    double[] res = new double[MONKEY_WORKLOAD];
    // turned rnd into a local variable instead of static
    Random rnd = new Random();
    while (!stop.get()) {
        jobsDone.incrementAndGet();
        if (sync) {
            synchronized (lock) {
                monkeyJob(res, rnd);
            }
        } else {
            monkeyJob(res, rnd);
        }
    }
}
...

private static double[] monkeyJob(double[] res, Random rnd) {
    for (int i = 0; i < res.length; i++) {
        res[i] = rnd.nextDouble();
        res[i] = 1. / (1. + res[i]);
    }
    return res;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 同步代码比非同步代码执行得更快 - Synchronized code performs faster than unsynchronized one Java内存模型:混合不同步和同步 - Java Memory Model: Mixing unsynchronized and synchronized 关于Java Collections Framework中的不同步和同步访问? - About unsynchronized & synchronized access in Java Collections Framework? 为什么一段 Java 代码在使用 synchronized 关键字时比不使用它更快? - Why is a block of Java code faster when using synchronized keyword, rather than without using it? Java CAS操作的执行速度比C等效的快,为什么? - Java CAS operation performs faster than C equivalent, why? 为什么非同步对象的性能优于同步对象? - Why do unsynchronized objects perform better than synchronized ones? 声纳:将同步类“Hashtable”替换为非同步类,例如“HashMap” - Sonar: Replace the synchronized class "Hashtable" by an unsynchronized one such as "HashMap" 设计和编写可以执行不同步或同步任务的任务调度程序 - Design and code a task scheduler that can take unsynchronized or synchronized tasks 同步和非同步方法的ConcurrentModificationException - ConcurrentModificationException with synchronized and unsynchronized methods 当 AtomicInteger 比同步更快时 - When AtomicInteger is faster than synchronized
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM