为什么RW锁比我的例子中的同步慢100ms

时间:2015-12-23 10:12:03

标签: java multithreading synchronized

我想表现出RW lock vs synchronized的性能差异。我已经完成了锁定部分,但我遇到了synchronized的问题。 add线程调用Producer方法,getRandomElement()线程调用Consumer。我想强制在没有人执行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));

    }

}

1 个答案:

答案 0 :(得分:0)

以下是方法。您可能需要尝试并修复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;
    } 

}