Day22:欧印万

在尚未出现java.util.concurrent套件以前,多执行绪的程序都需要自己设计wait(), notify(), notifyAll()等程序,一个设计不良还可能造成死结(deadlock)的状况。

在JDK5以後,就可以使用现成的java.util.concurrent套件来更便利的撰写多执行绪相关程序。

  • Lock

Lock介面常用的实作类别为ReentrantLock,可以透过呼叫lock()方法让执行绪取得锁,并以呼叫unlock()来释放锁:

private Lock lock = new ReentrantLock();
private Object[] array;
private int next;
public void add(E e){
    lock.lock();
    try{
        if(next == array.length){
            array = Arrays.copyOf(array, array.length * 2);
        }
        array[next++] = e;
    }finally{
        lock.unlock();
    }
}

除了基本的lock()以及unlock(),还有tryLock()方法,传回boolean,true表示可以取得锁,有了这个方法,原先产生死结的程序就可以透过呼叫tryLock()来解开死结。

  • ReadWriteLock (ReentrantReadWriteLock)

由於写入动作是产生多执行绪资料混乱的罪魁祸首,若让其他读取的动作也都进行同样的锁定程序,会导致效能低下,这时就可以用ReadWriteLock来增进程序的效能。

其原理为,读取动作使用readLock()来进行锁定,写入动作使用writeLock()来进行锁定。

当有执行绪企图取得readLock时,只要物件的writeLock没有被取走,那就可以被拿走;
当有执行绪企图取得writeLock时,条件不只是writeLock没有被取走,连readLock也没有被取走时,才能允许执行绪取得writeLock。

  • ReadWriteLock (StampLock)

上述的ReentrantReadWriteLock实作是比较严谨的执行绪锁定管控了,因为只要有任何执行绪再进行写入动作,也不能够读取,称为悲观读取(Pessimistic Reading)。假若我们的程序不需要这麽严格的管控呢?纵使被读取的物件状态会和真实状态不一样,但我们知道误差不会太大抑或是有误差我们无所谓,那就可以改用StampLock的实作类别。

long stamp = stampLock.tryOptimisticRead();
int num = array[i];
if(!stampLock.validate(stamp)){
    stamp = stampLock.readLock();
    try{
        num = array[i];
    }finally{
        stampLock.unlockRead(stamp);
    }
}
return num;
  • Condition

Condition的作用就是可以拥有不只一个物件的执行绪等待集,原生物件的wait(), notify()会共用该物件的等待集,所以不管执行绪原本是预备执行什麽动作,只要被叫进等待集,就是统一等待叫号;运用Condition物件的话,就可以依据需求将执行绪放进不同的等待集,当当前执行绪完成动作要教下一个来执行的时候,可以精准呼叫出该流程等待集中的执行绪,减少整体程序呼叫到无用执行绪的效能。

private Lock lock = new ReentrantLock();
private Condition aCondition = lock.newCondition();
private Condition bCondition = lock.newCondition();
public void aMethod(){
    lock.lock()
    try{
        isAOk();
        doSomething();
        bCondition.signal();  //相当於Object的notify()
    }finally{
        lock.unlock()
    }
}
public void isAOk(){
    if( someCondition() ){
        aCondition.await();  //相当於Object的wait()
    }
}
public void bMethod(){
    lock.lock()
    try{
        isBOk();
        doSomething();
        aCondition.signal();
    }finally{
        lock.unlock()
    }
}
public void isBOk(){
    if( someCondition() ){
        bCondition.await();
    }
}

<<:  Day 20 : 深度追踪 Depth-first-searh

>>:  [C 语言笔记--Day24] sleep

怎麽复制TABLE_SCHEMA里的table

SQL Server 1.一个一个TABLE去点,汇出Scripts 2.SQL Server 汇出...

Day 14 : PHP - 如何更改XAMPP里的phpMyAdmin的密码?

如标题,这篇想教大家如何修改phpMyAdmin的帐号密码 因为phpMyAdmin的预设是不用输入...

Day 8:IAM role、Policy建立

上篇我们学习到了如何再AWS Console建立user跟Group,今天我们来继续看如何建立rol...

[DAY 09]Discord Bot回覆带入图片方法

今天分享如何把图片放进先前的翻译及拍卖查询功能 在universalis上每个物品都会有张图片 点击...

Day27Java StringⅡ

接续昨天,来介绍第四种、第五种以及第六种方法! 4.代替Java String replace():...