Synchronized vs ReadWriteLock performance
<p>I try to prove that synchronized is slower when there are many readers and only some writers. Somehow I proved the opposite.</p>

<p>The RW example, time of execution is 313 ms:</p>

<pre><code>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(() -&gt; {
            end = System.currentTimeMillis();
            System.out.println("Time of execution " + (end - start) + " ms");
        }));
        start = System.currentTimeMillis();
        final int NUMBER_OF_THREADS = 1000;
        ThreadSafeArrayList&lt;Integer&gt; threadSafeArrayList = new ThreadSafeArrayList&lt;&gt;();
        ArrayList&lt;Thread&gt; consumerThreadList = new ArrayList&lt;Thread&gt;();
        for (int i = 0; i &lt; NUMBER_OF_THREADS; i++) {
            Thread t = new Thread(new Consumer(threadSafeArrayList));
            consumerThreadList.add(t);
            t.start();
        }

        ArrayList&lt;Thread&gt; producerThreadList = new ArrayList&lt;Thread&gt;();
        for (int i = 0; i &lt; 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&lt;Integer&gt; threadSafeArrayList;

    public Consumer(ThreadSafeArrayList&lt;Integer&gt; threadSafeArrayList) {
        this.threadSafeArrayList = threadSafeArrayList;
    }

    @Override
    public void run() {
        for (int j = 0; j &lt; NUMBER_OF_OPERATIONS; j++) {
            Integer obtainedElement = threadSafeArrayList.getRandomElement();
        }
    }

}
class Producer implements Runnable {
    public final static int NUMBER_OF_OPERATIONS = 100;
    ThreadSafeArrayList&lt;Integer&gt; threadSafeArrayList;

    public Producer(ThreadSafeArrayList&lt;Integer&gt; threadSafeArrayList) {
        this.threadSafeArrayList = threadSafeArrayList;
    }

    @Override
    public void run() {
        for (int j = 0; j &lt; NUMBER_OF_OPERATIONS; j++) {
            threadSafeArrayList.add((int) (Math.random() * 1000));
        }
    }

}

class ThreadSafeArrayList&lt;E&gt; {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private final Lock readLock = readWriteLock.readLock();

    private final Lock writeLock = readWriteLock.writeLock();

    private final List&lt;E&gt; list = new ArrayList&lt;&gt;();

    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();
    }

}
</code></pre>

<p>synchronized example, time of execution is only 241ms:</p>

<pre><code>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(() -&gt; {
            end = System.currentTimeMillis();
            System.out.println("Time of execution " + (end - start) + " ms");
        }));
        start = System.currentTimeMillis();
        final int NUMBER_OF_THREADS = 1000;
        List&lt;Integer&gt; list = Collections.synchronizedList(new ArrayList&lt;Integer&gt;());
        ArrayList&lt;Thread&gt; consumerThreadList = new ArrayList&lt;Thread&gt;();
        for (int i = 0; i &lt; NUMBER_OF_THREADS; i++) {
            Thread t = new Thread(new Consumer(list));
            consumerThreadList.add(t);
            t.start();
        }

        ArrayList&lt;Thread&gt; producerThreadList = new ArrayList&lt;Thread&gt;();
        for (int i = 0; i &lt; 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&lt;Integer&gt; list;

    public Consumer(List&lt;Integer&gt; list) {
        this.list = list;
    }

    @Override
    public void run() {
        for (int j = 0; j &lt; NUMBER_OF_OPERATIONS; j++) {
            if (list.size() &gt; 0)
                list.get((int) (Math.random() * list.size()));
        }
    }

}

class Producer implements Runnable {
    public final static int NUMBER_OF_OPERATIONS = 100;
    List&lt;Integer&gt; threadSafeArrayList;

    public Producer(List&lt;Integer&gt; threadSafeArrayList) {
        this.threadSafeArrayList = threadSafeArrayList;
    }

    @Override
    public void run() {
        for (int j = 0; j &lt; NUMBER_OF_OPERATIONS; j++) {
            threadSafeArrayList.add((int) (Math.random() * 1000));
        }
    }

}
</code></pre>

<p>Why synchronized collection is faster when I have ten times more readers than writers. How to show advance of RW locks about which I read in many articles?</p>