公平锁:
    优势:各线程平等,每个线程在等待一段时间后,总有执行的机会
    劣势:更慢,吞吐量更小
    非公平锁:
    优势:更快,吞吐量更大
    劣势:有可能产生线程饥饿,也就是某些线程长时间内,始终得不到执行(线程饥饿)

    读锁插队策略:::
    非公平:假设线程2和线程4正在同时读取,线程3想要写入,拿不到锁,于是进入等待队列,线程5不在队列里,现在过来想要读取。
    这种有2种策略: 策略1:读可以插队,效率高 ,但是容易造成饥饿,容易让写操作的线程陷入饥饿
    策略2:避免饥饿,排在头节点的写锁后面
    策略选择演示::
    策略的选择取决于具体锁的实现,ReentrantReadWriteLock的实现是选择了策略2,是很明智的。

    公平锁::不允许插队,排队,其他的只能尝试,但是不能获取锁成功
    非公平锁:写锁可以随时插队
    读锁仅在等待队列头节点不是想获取写锁的线程的时候可以插队,就是如果等待队列是写操作时不能插队的。这样说,好像读也不能插队,但是当等待队列头节点不是写操作就能插队;

    1. public class NofairReadWriteLock {
    2. private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(false);
    3. private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
    4. private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
    5. public static void main(String[] args) {
    6. new Thread(()->{ write(); },"Thread-1").start();
    7. new Thread(()->{ read(); },"Thread-2").start();
    8. new Thread(()->{ read(); },"Thread-3").start();
    9. // 写需要排队,写后面5,6线程读,但是当4作为等待队列头节点时,5,6需要在4后面排队,即使是非公平锁
    10. new Thread(()->{ write(); },"Thread-4").start();
    11. new Thread(()->{ read(); },"Thread-5").start();
    12. new Thread(()->{ read(); },"Thread-6").start();
    13. /**
    14. * Thread-1得到了写锁,正在写入
    15. * Thread-1释放写锁
    16. * Thread-2得到了读锁,正在读取
    17. * Thread-3得到了读锁,正在读取
    18. * Thread-3释放读锁
    19. * Thread-2释放读锁
    20. * Thread-4得到了写锁,正在写入
    21. * Thread-4释放写锁
    22. * Thread-5得到了读锁,正在读取
    23. * Thread-6得到了读锁,正在读取
    24. * Thread-6释放读锁
    25. * Thread-5释放读锁
    26. */
    27. }
    28. private static void read(){
    29. readLock.lock();
    30. try {
    31. System.out.println(Thread.currentThread().getName()+"得到了读锁,正在读取");
    32. Thread.sleep(1000);
    33. } catch (InterruptedException e) {
    34. e.printStackTrace();
    35. } finally {
    36. System.out.println(Thread.currentThread().getName()+"释放读锁");
    37. readLock.unlock();
    38. }
    39. }
    40. private static void write(){
    41. writeLock.lock();
    42. try {
    43. System.out.println(Thread.currentThread().getName()+"得到了写锁,正在写入");
    44. Thread.sleep(1000);
    45. } catch (InterruptedException e) {
    46. e.printStackTrace();
    47. } finally {
    48. System.out.println(Thread.currentThread().getName()+"释放写锁");
    49. writeLock.unlock();
    50. }
    51. }
    52. }