ReentrantLock和ReentrantReadWriteLock 比较

ReadWriteLock是Jdk5中提供读写分离锁,读写分离锁可以有效地帮助减少锁竞争,提升系统性能。如果使用重用锁或内部锁,理论上所有读之间、读写之间、写和写之间都是串行操作。然而读写所允许多个线程同时读,读写操作或者写写操作仍然需要相互等待和持有锁。在系统中如果读操作次数远远大于写操作次数,读写锁就可以发挥最大功效,提升系统性能。

ReentrantLock

import org.junit.Test;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestReadWriteLock {
    private static final int MAX_THREADS = 2000;
    private static final int TASK_COUNT = 4000;
    private static Lock lock = new ReentrantLock();
    java.util.Random rand = new java.util.Random();
    private int value;

    /**
     * ReentrantLock操作线程
     */
    public class ReadWriteThread implements Runnable {
        protected String name;

        public ReadWriteThread() {
        }

        public ReadWriteThread(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                handleRead();
                int v = rand.nextInt(100);
                if (v < 10) {
                    handleWrite(v);
                }
                Thread.sleep(rand.nextInt(100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 线程池
     */
    public class CounterPoolExecutor extends ThreadPoolExecutor {
        private AtomicInteger count = new AtomicInteger(0);
        public long startTime = 0;
        public String funcname = "";

        public CounterPoolExecutor(int corePoolSize, int maximumPoolSize,
                                   long keepAliveTime, TimeUnit unit,
                                   BlockingQueue workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }

        protected void afterExecute(Runnable r, Throwable t) {
            int l = count.addAndGet(1);
            if (l == TASK_COUNT) {
                System.out.println(funcname + " spend time:" + (System.currentTimeMillis() - startTime));

            }
        }
    }

    /**
     * ReentrantLock可重入锁
     *
     * @return
     * @throws InterruptedException
     */
    public Object handleRead() throws InterruptedException {
        try {
            lock.lock();
            Thread.sleep(1);
            return value;
        } finally {
            lock.unlock();
        }
    }

    /**
     * ReentrantLock可重入锁
     *
     * @param index
     * @throws InterruptedException
     */
    public void handleWrite(int index) throws InterruptedException {
        try {
            lock.lock();
            Thread.sleep(1);
            value = index;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 测试ReentrantLock
     *
     * @throws InterruptedException
     */
    @Test
    public void testLock() throws InterruptedException {

        CounterPoolExecutor exe = new CounterPoolExecutor(MAX_THREADS, MAX_THREADS,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue());

        long starttime = System.currentTimeMillis();
        exe.startTime = starttime;
        exe.funcname = "testLock";
        for (int i = 0; i < TASK_COUNT; i++)
            exe.submit(new ReadWriteThread());

        Thread.sleep(100000);
    }
}

输出结果

testLock spend time:6604

 
  
ReentrantReadWriteLock
import org.junit.Test;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriteLock {
    private static final int MAX_THREADS = 2000;
    private static final int TASK_COUNT = 4000;
    private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private static Lock readLock = readWriteLock.readLock();
    private static Lock writeLock = readWriteLock.writeLock();

    java.util.Random rand = new java.util.Random();
    private int value;

    /**
     * ReentrantReadWriteLock操作线程
     */
    public class ReadWriteThread2 implements Runnable {
        protected String name;

        public ReadWriteThread2() {
        }

        public ReadWriteThread2(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                handleRead2();
                int v = rand.nextInt(100);
                if (v < 10) {
                    handleWrite2(v);
                }
                Thread.sleep(rand.nextInt(100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 线程池
     */
    public class CounterPoolExecutor extends ThreadPoolExecutor {
        private AtomicInteger count = new AtomicInteger(0);
        public long startTime = 0;
        public String funcname = "";

        public CounterPoolExecutor(int corePoolSize, int maximumPoolSize,
                                   long keepAliveTime, TimeUnit unit,
                                   BlockingQueue workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }

        protected void afterExecute(Runnable r, Throwable t) {
            int l = count.addAndGet(1);
            if (l == TASK_COUNT) {
                System.out.println(funcname + " spend time:" + (System.currentTimeMillis() - startTime));

            }
        }
    }


    /**
     * ReentrantReadWriteLock
     *
     * @return
     * @throws InterruptedException
     */
    public Object handleRead2() throws InterruptedException {
        try {
            readLock.lock();
            Thread.sleep(1);
            return value;
        } finally {
            readLock.unlock();
        }
    }

    /**
     * ReentrantReadWriteLock
     *
     * @param index
     * @throws InterruptedException
     */
    public void handleWrite2(int index) throws InterruptedException {
        try {
            writeLock.lock();
            Thread.sleep(1);
            value = index;
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 测试读写锁ReentrantReadWriteLock
     *
     * @throws InterruptedException
     */
    @Test
    public void testLock2() throws InterruptedException {
        CounterPoolExecutor executor = new CounterPoolExecutor(MAX_THREADS, MAX_THREADS,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue());

        long starttime = System.currentTimeMillis();
        executor.startTime = starttime;
        executor.funcname = "testLock2";
        for (int i = 0; i < TASK_COUNT; i++) {
            executor.submit(new ReadWriteThread2());
        }
        Thread.sleep(100000);
    }
}

输出结果

testLock2 spend time:1102

你可能感兴趣的:(JDK并发数据结构)