Art of Multiprocessor Programming 答案 ch8

来源:互联网 发布:mac移动硬盘隐藏文件 编辑:程序博客网 时间:2024/04/30 10:37

93.

package p93;import java.util.concurrent.locks.Lock;public class SimpleRWLock{private class ReadLock implements Lock{public void lock(){try{synchronized(lockObj){while(writer){lockObj.wait();}readers ++;}}catch(Exception e){e.printStackTrace();}} public void unlock(){synchronized(lockObj){if(readers <= 0){lockObj.notifyAll();}}}public void lockInterruptibly() throws java.lang.InterruptedException{throw new InterruptedException();}  public boolean tryLock(){return false;}  public boolean tryLock(long arg0, java.util.concurrent.TimeUnit arg1) throws java.lang.InterruptedException{throw new InterruptedException();}  public java.util.concurrent.locks.Condition newCondition(){return null;}}private class WriteLock implements Lock{public void lock(){try{synchronized(lockObj){while(readers > 0 || writer){lockObj.wait();}writer =  true;}}catch(Exception e){e.printStackTrace();}} public void unlock(){synchronized(lockObj){writer = false;lockObj.notifyAll();}}public void lockInterruptibly() throws java.lang.InterruptedException{throw new InterruptedException();}  public boolean tryLock(){return false;}  public boolean tryLock(long arg0, java.util.concurrent.TimeUnit arg1) throws java.lang.InterruptedException{throw new InterruptedException();}  public java.util.concurrent.locks.Condition newCondition(){return null;}}private int readers;private boolean writer;private Object lockObj;private ReadLock readLock;private WriteLock writeLock;public SimpleRWLock(){lockObj = new Object();readLock = new ReadLock();writeLock = new WriteLock();}public Lock readLock(){return readLock;}public Lock writeLock(){return writeLock;}public static void main(String[] args){SimpleRWLock lock = new SimpleRWLock();lock.readLock().lock();lock.readLock().unlock();lock.writeLock().lock();lock.writeLock().unlock();}}


94.

会有  readlock.lock() --> readwait > readrelease --> writelock.lock() --> write = true --> waiting for readwait == readrelease ==> deadlock

其他的线程会有 write == true ==> block


95. 不一定全部会返回,因为可能在别人的cond上死锁,boss notify自己的锁线程感应不到。比如下面的case:

package p95;public class Prefer {private int balance;private int preferRequests;public static final int PREFER = 1;public static final int NORMAL = 2;public Prefer(){balance = 0;preferRequests = 0;}public Prefer(int initial){this();balance = initial;}private void deposit_nolock(int k){balance += k;}public synchronized void deposit(int k){deposit_nolock(k);this.notifyAll();}public synchronized void withdraw(int k, int style){try{switch(style){case NORMAL:while(preferRequests > 0 || balance < k){this.wait();}balance -= k;break;case PREFER:preferRequests ++;while(balance < k){this.wait();}balance -= k;preferRequests --;this.notifyAll();break;default:throw new InterruptedException();}}catch(InterruptedException e){this.notifyAll();}}public synchronized void transfer(Prefer other, int k){other.withdraw(k, NORMAL);deposit_nolock(k);}} 

package p95;public class TestThread extends Thread{private Prefer myAccount;private Prefer otherAccount;public final int WITHDRAW = 200;public final int BOSS = 1000;public TestThread(Prefer me, Prefer other){this.myAccount = me;this.otherAccount = other;}public void run(){System.out.println("To transfer ");myAccount.transfer(otherAccount, WITHDRAW);System.out.println("End of transfer ");}public void boss(){myAccount.deposit(BOSS);}public static void main(String[] args){Prefer[] accounts = new Prefer[2];for(int i = 0; i < accounts.length; i ++){accounts[i] = new Prefer(0);}TestThread tester1 = new TestThread(accounts[0], accounts[1]);TestThread tester2 = new TestThread(accounts[1], accounts[0]);tester1.start();tester2.start();try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}System.out.println("After sleep ");tester1.boss();tester2.boss();}}

96.

package p96;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Bathroom_1{private Lock lock;private Condition maleCond;private Condition femaleCond;private int maleAcq;private int maleRel;private int femaleAcq;private int femaleRel;private int maleWait;private int femaleWait;public static final int MALE = 1;public static final int FEMALE = 2;public Bathroom_1(){lock = new ReentrantLock();maleCond = lock.newCondition();femaleCond = lock.newCondition();}public void maleEnter(){lock.lock();try{maleWait ++;while((femaleWait != femaleAcq && maleAcq != maleRel) || (femaleAcq != femaleRel)){maleCond.await();}maleAcq ++;}catch(Exception e){e.printStackTrace();maleWait --;maleCond.signalAll();femaleCond.signalAll();}finally{lock.unlock();}}public void maleExit(){lock.lock();maleRel ++;if(maleRel == maleAcq){femaleCond.signalAll();}lock.unlock();}public void femaleEnter(){lock.lock();try{femaleWait ++;while((maleWait != maleAcq && femaleAcq != femaleRel) || (maleAcq != maleRel)){femaleCond.await();}femaleAcq ++;}catch(Exception e){e.printStackTrace();femaleWait --;maleCond.signalAll();femaleCond.signalAll();}finally{lock.unlock();}}public void femaleExit(){lock.lock();femaleRel ++;if(femaleRel == femaleAcq){maleCond.signalAll();}lock.unlock();}}

97.

package p97;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Rooms{public interface Handler{void onEmpty();}private Lock lock;private Condition[] conds;private int waiting[];private int acquire[];private int release[];private Handler[] handlers;private final int m;private int currRoom;public Rooms(int m){this.m = m;lock = new ReentrantLock();conds = new Condition[m + 1];for(int i = 0; i < conds.length; i ++){conds[i] = lock.newCondition();}waiting = new int[m + 1];acquire = new int[m + 1];release = new int[m + 1];handlers = new Handler[m + 1];currRoom = -1;}private boolean toWait(int index){if(currRoom == -1){return false;}if(currRoom != index){return true;}for(int i = 1; i <= m; i ++){int other = (i + index) % (m + 1);if(waiting[other] != acquire[other]){return true;}}return false;}public void enter(int i){if(i < 0 || i > m){return;}lock.lock();try{waiting[i] ++;while(toWait(i)){conds[i].await();}acquire[i] ++;currRoom = i;}catch(Exception e){e.printStackTrace();}finally{lock.unlock();}}private int notifyWho(){for(int i = 1; i <= m; i ++){int other = (i + currRoom) % (m + 1);if(waiting[other] != acquire[other]){return other;}}return -1;}public boolean exit(){lock.lock();release[currRoom] ++;if(release[currRoom] == acquire[currRoom]){if(handlers[currRoom] != null){handlers[currRoom].onEmpty();}int other = notifyWho();if(other >= 0){conds[other].signalAll();}currRoom = -1;}lock.unlock();return true;}public void setExitHandler(int i, Rooms.Handler handler){if(i < 0 || i > m){return;}lock.lock();handlers[i] = handler;lock.unlock();}}


98.

package p98;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class CountDownLatch {private Lock lock;private Condition cond;private int m;public CountDownLatch(int m){this.m = m;lock = new ReentrantLock();cond = lock.newCondition();}public void countDown(){lock.lock();m --;if(m <= 0){cond.signalAll();}lock.unlock();}public void await(){lock.lock();try{while(m > 0){cond.await();}}catch(Exception e){e.printStackTrace();}finally{lock.unlock();}}/* * Lock is not necessary as: * 1.set m at anytime can get matching history * 2.User should take care of reset since I don't want to block reset() method */public void reset(int m){lock.lock();this.m = m;lock.unlock();}}


0 0