您的位置:首页 > 其它

Art of Multiprocessor Programming 答案 ch8

2014-04-15 20:15 387 查看
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: