性能
虽然Synchronized和标准的ReentrantLock性能差别不大,但是ReentrantLock还提供了一种非互斥的读写锁,
也就是不强制每次最多只有一个线程能持有锁,它会避免“读/写”冲突,“写/写”冲突,但是不会排除“读/读”冲突,
因为“读/读”并不影响数据的完整性,所以可以多个读线程同时持有锁,这样在读写比较高的情况下,性能会有很大的提升。
下面用两种锁分别实现的线程安全的linkedlist:
class RWLockList {//读写锁 private List list; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); public RWLockList(List list){this.list = list;} public int get(int k) { readLock.lock(); try { return (int)list.get(k); } finally { readLock.unlock(); } } public void put(int value) { writeLock.lock(); try { list.add(value); } finally { writeLock.unlock(); } } }class SyncList { private List list; public SyncList(List list){this.list = list;} public synchronized int get(int k){ return (int)list.get(k); } public synchronized void put(int value){ list.add(value); } } |
读写锁测试代码:
List list = new LinkedList();for (int i=0;i<10000;i++){ list.add(i); } RWLockList rwLockList = new RWLockList(list);//初始化数据Thread writer = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ rwLockList.put(i); } } }); Thread reader1 = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ rwLockList.get(i); } } }); Thread reader2 = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ rwLockList.get(i); } } });long begin = System.currentTimeMillis(); writer.start();reader1.start();reader2.start();try { writer.join(); reader1.join(); reader2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("RWLockList take "+(System.currentTimeMillis()-begin) + "ms"); |
同步锁测试代码:
List list = new LinkedList();for (int i=0;i<10000;i++){ list.add(i); } SyncList syncList = new SyncList(list);//初始化数据Thread writerS = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ syncList.put(i); } } }); Thread reader1S = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ syncList.get(i); } } }); Thread reader2S = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<10000;i++){ syncList.get(i); } } });long begin1 = System.currentTimeMillis(); writerS.start();reader1S.start();reader2S.start();try { writerS.join(); reader1S.join(); reader2S.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("SyncList take "+(System.currentTimeMillis()-begin1) + "ms"); |
结果:
RWLockList take 248msRWLockList take 255msRWLockList take 249msRWLockList take 224msSyncList take 351msSyncList take 367msSyncList take 315msSyncList take 323ms
可见读写锁的确是优于纯碎的互斥锁
总结
内置锁最大优点是简洁易用,显示锁最大优点是功能丰富,所以能用内置锁就用内置锁,在内置锁功能不能满足之时在考虑显示锁。
关于两种锁,目前接触到的就是这么多,总结不到位之处,欢迎拍砖。