java线程 同步临界区:thinking in java4 21.3.5
thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155
package org.rui.thread.critical;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 临界区
*
*
*
* Pair不是线程安全的,由于它的约束条件(尽管是随意的) 须要两个变量维护成同样的值。
* 此外,如本章前面所述,自添加操作不是线程安全的,
* 而且由于没有不论什么方法被标记为synchronized。所以不能保证一个pair对象在多线程程序中不会破坏.
* @author lenovo
*
*/
//org.rui.thread.critical.CriticalSection.java
class Pair
{
private int x,y;
public Pair(int x,int y)
{
this.x=x;
this.y=y;
}
public Pair(){this(0,0);}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void incrementX(){x++;}
public void incrementY(){y++;}
public String toString()
{
return "x: "+x+" , y:"+y;
}
/////////////////PariValuesNotEqualException
public class PariValuesNotEqualException extends RuntimeException
{
public PariValuesNotEqualException()
{
super("Pair values not equal:"+Pair.this);
}
}
//随意变,两个变量必须是平等的
//Arbitrary invariant --both variables must be equal:
public void checkState()
{
if(x!=y)
{
throw new PariValuesNotEqualException();
}
}
}//Pair end
//保护一对在一个线程安全的类
//protect a pair inside a thread -safe class:
abstract class PairManager
{
AtomicInteger checkCounter=new AtomicInteger(0);
protected Pair p=new Pair();
private List<Pair> storage=Collections.synchronizedList(new ArrayList<Pair>());
public synchronized Pair getPair()
{
//复制的原始安全:
//Make a copy to keep the original safe:
return new Pair(p.getX(),p.getY());
}
//如果这是一个耗时的操作
//Assume this is a time consuming operation
protected void store(Pair p)
{
storage.add(p);
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//
public abstract void increment();
}
//整个同步方法
//synchronize the entire method
class PairManager1 extends PairManager
{
@Override
public synchronized void increment()
{
p.incrementX();
p.incrementY();
store(getPair());
}
}
//use a critical section: 使用临界区
class PairManager2 extends PairManager
{
public void increment()
{
Pair temp;
synchronized(this)
{
p.incrementX();
p.incrementY();
temp=getPair();
}
store(temp);
}
}
///操作者
class PairManipulator implements Runnable
{
private PairManager pm;
public PairManipulator(PairManager pm)
{
this.pm=pm;
}
@Override
public void run()
{
while(true)
pm.increment();
}
public String toString()
{
return "Pair: "+pm.getPair()+" checkCounter= "+pm.checkCounter.get();
}
}
////PairChecker
class PairChecker implements Runnable
{
private PairManager pm;
public PairChecker(PairManager pm)
{
this.pm=pm;
}
@Override
public void run() {
while(true)
{
pm.checkCounter.incrementAndGet();
pm.getPair().checkState();
}
}
}
/////////////////////////////////////////////////////////
public class CriticalSection {
//測试两种不同的方法
//test the two defferent approaches
static void testApproaches(PairManager pman1,PairManager pman2)
{
ExecutorService exec=Executors.newCachedThreadPool();
PairManipulator pm1=new PairManipulator(pman1);
PairManipulator pm2=new PairManipulator(pman2);
PairChecker pcheck1=new PairChecker(pman1);
PairChecker pcheck2=new PairChecker(pman2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException");
}
System.out.println("pm1:"+pm1+"
pm2:"+pm2);
System.exit(0);
}
public static void main(String[] args) {
PairManager pman1=new PairManager1(),
pman2=new PairManager2();
testApproaches(pman1,pman2);
}
}
/**output:(sample)
pm1:Pair: x: 8 , y:8 checkCounter= 674247
pm2:Pair: x: 8 , y:8 checkCounter= 5043736
*/
package org.rui.thread.critical;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 你还能够使用显示的lock对象来创建临界区
*
* 这里利用了CriticalSection.java的绝大部分,
* 并创建了新的使用显式的lock对象的PairManger类型。
* expliciPariManger2展示了怎样使用Lock对象来创建临界区,而对store()的调用则在这个临界区的外部
* @author lenovo
*
*/
//////////////////////////
class ExplicitPairManager1 extends PairManager {
private Lock lock =new ReentrantLock();
@Override
public synchronized void increment()
{
lock.lock();
try{
p.incrementX();
p.incrementY();
store(getPair());
}finally{
lock.unlock();
}
}
}
//use a critical section
class ExplicitPairManager2 extends PairManager
{
private Lock lock =new ReentrantLock();
@Override
public void increment() {
Pair temp=null;
lock.lock();
try{
p.incrementX();
p.incrementY();
temp=getPair();
}finally{
lock.unlock();
}
store(temp);
}
}
/////////////////
public class ExplicitCriticalSection {
public static void main(String[] args)
{
PairManager pman1=new PairManager1(),
pman2=new PairManager2();
CriticalSection.testApproaches(pman1,pman2);
}
}
/**
* output:
pm1:Pair: x: 10 , y:10 checkCounter= 195142
pm2:Pair: x: 11 , y:11 checkCounter= 4129459
*/