读书笔记——《Java多线程编程核心技术》第四章

第四章主要讲的是Lock的使用。

ReentrantLock类

使用ReentrantLock可以实现同步,Condition实现等待/通知。Condition对象可以创建多个,实现只通知部分线程,而不像notifyAll()那样通知所有线程然后交给线程调度器随机通知一个线程,从而提高了效率。

Object类中的wait()方法相当于Condition类中的await()方法。
Object类中的wait(long timeout)方法相当于Condition类中的await(long time,TimeUnit unit)方法。
Object类中的notify()方法相当于Condition类中的signal()方法。
Object类中的notifyAll()方法相当于Condition类中的signalAll()方法。

公平锁
获得锁的时机基本和线程启动的顺序一致。

lock = new ReentrantLock(isFair);

非公平锁

获得锁的时机和线程启动的顺序基本不一致。

介绍几个常用的方法:

  1. getHoldCount()、getQueueLength()、getWaitQueueLength()

getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。

getQueueLength():返回正等待获取此锁定的线程估计数。

getWaitQueueLength(Condition condition):返回等待与此锁定相关的给定条件Condition的线程估计数。

  1. hasQueuedThread()、hasQueuedThreads()、hasWaiters()

boolean hasQueuedThread(Thread thread):查询指定线程是否正在等待获取此锁定。

boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的condition条件。

  1. isFair()、isHeldByCurrentThread()、isLocked()

boolean isFair():判断是不是公平锁。

boolean isHeldByCurrentThread()作用是查询当前线程是否保持此锁定。

boolean isLocked():查询此锁定是否有由任意线程保持。

  1. lockInterruptibly()、tryLock()、tryLock(long timeout,TimeUnit unit)

void lockInterruptibly():如果当前线程未被中断则获取锁定,如果被中断了则出现异常。

boolean tryLock():仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。

boolean tryLock(long timeout,TimeUnit unit):如果锁定在给定时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。

  1. awaitUninterruptibly():

    public class Service9 {

    private ReentrantLock lock = new ReentrantLock();
    
    private Condition condition = lock.newCondition();
    
    public void testMethod(){
    
        try{
            lock.lock();
            System.out.println("wait begin");
            //condition.await(); 线程在等待的时候interrupt则会出现异常
            condition.awaitUninterruptibly();//不会出现异常
            System.out.println("wait   end");
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("catch");
        }finally{
            lock.unlock();
        }
    }
    

    }

    Main方法如下:

    public class Run22 {

    public static void main(String[] args) {
    
        try{
            Service9 service = new Service9();
            MyThread2 myThread = new MyThread2(service);
            myThread.start();
            Thread.sleep(3000);
            myThread.interrupt();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    

    }

    如果我们用await(),当线程中断的时候会出现异常,用awaitUninterruptibly(),当线程中断的时候不会出现异常。

  2. awaitUntil():线程等待一段时间后自己唤醒。

ReentrantReadWriteLock类

ReentrantLock具有完全互斥排他的效果,这样做虽然保证了完全的线程安全,但是效率不高,所以引入了ReentrantReadWriteLock类。读写锁有两个锁,一个是读操作相关的锁,被称为共享锁。另一个是写操作相关的锁,被称为排他锁。多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。

主要讲的是Lock相关的东西,较synchronized更为高效的东西。