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

4.1.1
        原:调用ReentrantLock对象的lock()方法获取锁,调用unlock()方法释放锁。P201
        Lock lock = new ReentrantLock();
        如果不调用lock.unlock()释放锁,那么即使线程任务结束,仍然不会释放锁抛出异常也不会释放锁

4.1.2
        原:调用lock.lock()代码的线程就持有了“对象监视器”,其它线程只有等待锁被释放时再次争抢。P204

4.1.3
        Condition对象通过ReentrantLock对象生成。Condition condition = lock.newCondition();
        Condition的await()方法让持有lock锁的对象暂停,并释放同步锁

4.1.4
        另外一个线程获取到同步锁,采用condition.signal()唤醒暂停休眠的线程。
        但值得注意的是,与notify()方法一样,刚苏醒的线程需要等待其它线程执行完毕,释放锁后,才能继续执行。

        condtion在调用await()方法和signal()方法之前,需要先调用lock.lock()保证在同步环境中才可执行
        condition.signal();一次只唤醒一个暂停的线程。

4.1.6
        一个ReentrantLock对象可以生成多个Condition对象。
        哪个线程中的condition对象调用了await()方法,
        在别的线程中调用同一个condition的signal()方法唤醒的就是哪个线程。

4.1.9
        ReentrantLock的构造函数接收一个 boolean 类型的数值。
        Lock lock = new ReentrantLock(boolean b);
        如果boolean为true,那么此锁就是公平锁
        哪个线程先进入可执行状态,哪个线程优先获取 lock.lock()的锁。
        默认为false,就是常规的非公平锁。进入可执行状态的线程,进行争夺同步锁。默认是非公平锁

4.1.10
        ReentrantLock的getHoldCount(),作用是当前线程中调用了几次lock.lock()
        有点像锁重入的意思,当前线程调用的方法内部调用另外一个方法,那个方法也
        需要同步锁,需要调用lock.lock(),那么是可以进入的。

        ReentrantLock的lock.getQueueLength()   返回同步队列的长度

        ReentrantLock的lock.getWaitQueueLength(Condition) 返回指定condition对象的等待队列的长度

4.1.11
        ReentrantLock的lock.hasQueuedThread(Thread thread) 查看是否有指定的thread在等待当前的线程释放lock锁
        ReentrantLock的lock.hasQueuedThreads() 查看是否有其它线程在等待当前的线程释放锁。
        ReentrantLock的lock.hasWaiters(Condition condition) 当前lock是否有condition让其它线程等待了

4.1.12
        ReentrantLock的isFair()判断是否是公平锁
        ReentrantLock的isHeldByCurrentThread()判断当前线程是否保持锁定,很有用,判断当前线程是否还有锁。

4.1.13
        lock.lock();获取同步
        lock.lockInterruptibly();获取同步,并检测线程中断状态位,一旦线程中断,则抛出异常而释放锁。所以有try-catch语句监控
        if(lock.tryLock()){ A代码; }else{  B代码; } 如果获取不到同步锁,那么就执行B了,不然干等等到什么时候。
        if(lock.tryLock(3,TimeUnit.SECONDS)){ A代码; }else{  B代码; }  如果等了3秒还没有锁,那么执行B代码。
        tryLock可以用于获取数据库连接。等待多少秒连接池没有连接,那么就创建一个。

4.1.14
        ReentrantLock的生成的Condtion对象的condition.awaitUninterruptibly()
        它让线程在睡眠期间即使线程被中断,也不报中断异常。当然了,锁跟await()一样,会释放。
        Thread.sleep方法,是被try-catch进行监控的,一旦线程中断状态位被置为true,则抛中断异常,并释放同步锁。

        注意:lock锁,即使抛出异常也不放,必须执行lock.unlock()才能释放同步锁


4.2

        ReentrantReadWriteLock是读写锁
        原:多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。P236
        原:多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。P236

4.2.1
        创建读写锁
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        获取读锁并开启
        lock.readLock().lock();

        同样的,也要释放
        lock.readLock().unlock();

        创建写锁并开启
        lock.writeLock().lock();

        有一个方法,获取了写锁,并lock.writeLock().lock(); 
        在此写锁执行任务完毕,若不执行 lock.writeLock().unlock();其它线程都要等待

        原:读写,写读,写写 都是互斥的,而 读读 是非互斥,是异步的。P240

---------------------------------------------------

        ReentranceLock 等 同步组件,内部都用了 队列同步器AQS 实现。

        队列同步器(简称:同步器)AbstractQueuedSynchronizer(英文简称:AQS)
        它使用了一个 int 成员变量表示同步状态,通过内置的 先进先出Node队列来完成资源获取和线程的排队工作。

        队列同步器中的int成员变量的作用是:标记共享变量的状态(是否已经被其他线程锁住等)
        先进先出的队列用来存储没有获得到同步锁的线程。

        一般我们在一个同步类中,使用 嵌套类 来 继承 队列同步器AQS。同步器既可以支持独占式地获取同步状态,也可以支持共享式地获取同步状态,这样就可以方便实现不同类型的同步组(ReentrantLock、ReentrantReadWriteLock)

        同步组件的锁是给客户端用的。而同步器是锁的内部类,AQS是同步器的父类,提供了操作同步状态、线程管理的相关操作

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.

posted @ 2022-07-17 12:15  小大宇  阅读(13)  评论(0编辑  收藏  举报