java – Synchronized vs ReadWriteLock性能
我试图证明当有许多读者和只有一些作者时,synchronized会变慢.不知怎的,我证明了相反.
RW示例,执行时间为313 ms: package zad3readWriteLockPerformance; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Main { public static long start,end; public static void main(String[] args) { Runtime.getRuntime().addShutdownHook(new Thread(() -> { end = System.currentTimeMillis(); System.out.println("Time of execution " + (end - start) + " ms"); })); start = System.currentTimeMillis(); final int NUMBER_OF_THREADS = 1000; ThreadSafeArrayList<Integer> threadSafeArrayList = new ThreadSafeArrayList<>(); ArrayList<Thread> consumerThreadList = new ArrayList<Thread>(); for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread t = new Thread(new Consumer(threadSafeArrayList)); consumerThreadList.add(t); t.start(); } ArrayList<Thread> producerThreadList = new ArrayList<Thread>(); for (int i = 0; i < NUMBER_OF_THREADS/10; i++) { Thread t = new Thread(new Producer(threadSafeArrayList)); producerThreadList.add(t); t.start(); } // System.out.println("Printing the First Element : " + threadSafeArrayList.get(1)); } } class Consumer implements Runnable { public final static int NUMBER_OF_OPERATIONS = 100; ThreadSafeArrayList<Integer> threadSafeArrayList; public Consumer(ThreadSafeArrayList<Integer> threadSafeArrayList) { this.threadSafeArrayList = threadSafeArrayList; } @Override public void run() { for (int j = 0; j < NUMBER_OF_OPERATIONS; j++) { Integer obtainedElement = threadSafeArrayList.getRandomElement(); } } } class Producer implements Runnable { public final static int NUMBER_OF_OPERATIONS = 100; ThreadSafeArrayList<Integer> threadSafeArrayList; public Producer(ThreadSafeArrayList<Integer> threadSafeArrayList) { this.threadSafeArrayList = threadSafeArrayList; } @Override public void run() { for (int j = 0; j < NUMBER_OF_OPERATIONS; j++) { threadSafeArrayList.add((int) (Math.random() * 1000)); } } } class ThreadSafeArrayList<E> { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock readLock = readWriteLock.readLock(); private final Lock writeLock = readWriteLock.writeLock(); private final List<E> list = new ArrayList<>(); public void add(E o) { writeLock.lock(); try { list.add(o); //System.out.println("Adding element by thread" + Thread.currentThread().getName()); } finally { writeLock.unlock(); } } public E getRandomElement() { readLock.lock(); try { //System.out.println("Printing elements by thread" + Thread.currentThread().getName()); if (size() == 0) { return null; } return list.get((int) (Math.random() * size())); } finally { readLock.unlock(); } } public int size() { return list.size(); } } 同步示例,执行时间仅为241ms: package zad3readWriteLockPerformanceZMIENONENENASYNCHRO; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Main { public static long start,end; public static void main(String[] args) { Runtime.getRuntime().addShutdownHook(new Thread(() -> { end = System.currentTimeMillis(); System.out.println("Time of execution " + (end - start) + " ms"); })); start = System.currentTimeMillis(); final int NUMBER_OF_THREADS = 1000; List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>()); ArrayList<Thread> consumerThreadList = new ArrayList<Thread>(); for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread t = new Thread(new Consumer(list)); consumerThreadList.add(t); t.start(); } ArrayList<Thread> producerThreadList = new ArrayList<Thread>(); for (int i = 0; i < NUMBER_OF_THREADS / 10; i++) { Thread t = new Thread(new Producer(list)); producerThreadList.add(t); t.start(); } // System.out.println("Printing the First Element : " + threadSafeArrayList.get(1)); } } class Consumer implements Runnable { public final static int NUMBER_OF_OPERATIONS = 100; List<Integer> list; public Consumer(List<Integer> list) { this.list = list; } @Override public void run() { for (int j = 0; j < NUMBER_OF_OPERATIONS; j++) { if (list.size() > 0) list.get((int) (Math.random() * list.size())); } } } class Producer implements Runnable { public final static int NUMBER_OF_OPERATIONS = 100; List<Integer> threadSafeArrayList; public Producer(List<Integer> threadSafeArrayList) { this.threadSafeArrayList = threadSafeArrayList; } @Override public void run() { for (int j = 0; j < NUMBER_OF_OPERATIONS; j++) { threadSafeArrayList.add((int) (Math.random() * 1000)); } } } 当我的读者数量比作者多十倍时,为什么同步收集会更快.如何显示我在许多文章中读到的RW锁的进展? 解决方法
获取ReadWriteLock的实际成本通常比获取简单互斥锁的成本要慢得多. ReadWriteLock的
javadoc进入:
因此,您的线程执行非常简单的操作这一事实可能意味着性能主要取决于实际获取锁定所花费的时间. 您的基准测试还有另一个问题,即Math.random是同步的.从javadoc开始:
因此,即使您的并发读者在获取ReadWriteLock时没有相互阻塞,他们仍然可能会争夺在Math.random中获取的锁,从而打败了使用ReadWriteLock的一些优势.您可以通过使用ThreadLocalRandom来改进这一点.此类的用法通常应为以下形式:ThreadLocalRandom.current().nextX(…)(其中X为Int,Long等). 此外,正如assylias指出的那样,没有考虑JIT编译和其他运行时怪癖的天真Java基准测试是不可靠的.你应该使用Java Microbenchmarking Harness (JMH)这样的基准测试. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |