Synchronized java code performs times faster than unsynchronized one
我在一个高并发应用上工作。在应用程序代码中,我尽量避免同步。最近,在比较非同步和同步代码版本的测试性能时,发现同步代码的执行速度比非同步代码的执行速度快三倍四倍。
经过一些实验,我得出了这个测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 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; } |
我处理了线程数量、工作负载、测试迭代——每次同步代码的执行速度都比未经同步的快得多。
下面是两个不同的线程num_值的结果
Number of threads:3
syncLockTest, sync=true
Jobs
done 5951
Jobs done 5958
Jobs done 5878
syncLockTest,
sync=false
Jobs done 1399
Jobs done 1397
Jobs
done 1391Number of threads:5
syncLockTest, sync=true
Jobs
done 5895
Jobs done 6464
Jobs done 5886
syncLockTest,
sync=false
Jobs done 1179
Jobs done 1260
Jobs
done 1226
号
测试环境Windows 7专业版Java版本7
这里有一个类似的案例同步代码比不同步代码执行得更快
有什么想法吗?
Random是一个线程安全类。通过围绕主作业同步,您很可能避免了对调用到随机类中的争用。
这很吸引人。我想是@jtahlborn钉的。如果我移动
以下是我和一个
1 2 3 4 5 6 7 8 | syncLockTest, sync=true Jobs done 8800 Jobs done 8839 Jobs done 8896 syncLockTest, sync=false Jobs done 1401 Jobs done 1381 Jobs done 1423 |
下面是我的时间,每个线程使用一个
1 2 3 4 5 6 7 8 | 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 |
号
我还想知道这是否与GC有关,但将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ... @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; } |