[英]Why RW lock is slower by 100ms than synchronized in my example
我想展示一下性能RW锁与同步锁的区别。 我已经做了锁的一部分,但我有问题synchronized
。 Producer
线程调用add
方法, Consumer
线程调用getRandomElement()
。 我想强制使add()
方法被执行而没有人执行getRandomElement()
方法,以及getRandomElement()
方法时,没有人执行add()
的使用方法synchronized
字。
可能吗?
import java.util.ArrayList;
import java.util.List;
public class ThreadSafeArrayList<E> {
private final List<E> list = new ArrayList<>();
private final Object m = new Object();
public void add(E o) {
synchronized (m) {
list.add(o);
System.out.println("Adding element by thread" + Thread.currentThread().getName());
}
}
public E getRandomElement() {
synchronized (m) {
System.out.println("Printing elements by thread" + Thread.currentThread().getName());
if (size() == 0) {
return null;
}
return list.get((int) (Math.random() * size()));
}
}
public int size() {
return list.size();
}
}
RW版本由于某些原因而较慢,但应该更快:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public 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();
}
}
以下类在RW和同步版本中完全相同。
生产者类:
public 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));
}
}
}
Consumer
类:
public 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();
}
}
}
和主要:
import java.util.ArrayList;
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) + " milisekund");
}));
start = System.currentTimeMillis();
final int NUMBER_OF_THREADS = 100;
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; i++) {
Thread t = new Thread(new Producer(threadSafeArrayList));
producerThreadList.add(t);
t.start();
}
// System.out.println("Printing the First Element : " + threadSafeArrayList.get(1));
}
}
下面是方法。 您可能需要尝试并修复while循环。 另外,您可能需要同步列表对象而不是包含类的方法
public synchronized void add(E o) {
try {
list.add(o);
notifyAll();
System.out.println("Adding element by thread" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized E getRandomElement() {
try {
System.out.println("Printing elements by thread" + Thread.currentThread().getName());
while(true){
wait();
if(list.size()>0) break;
}
E ret = list.get((int) (Math.random() * size()));
return ret;
} catch (Exception e) {
return null;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.