package concurrency.lock;
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;
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 incrementsX(){ x++; }
public void incrementsY(){ y++; }
@Override
public String toString()
{
return "x: " + x + ", y: " + y;
}
public class PairValuesNotEqualException extends RuntimeException
{
// private static final long serialVersionUID = 1720136381044242317L;
public PairValuesNotEqualException()
{
super("Pair values not equal: " + Pair.this);
}
}
public void checkState()
{
if(x != y)
{
throw new PairValuesNotEqualException();
}
}
}
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()
{
return new Pair(p.getX(),p.getY());
}
protected void store(Pair p)
{
storage.add(p);
try
{
TimeUnit.MILLISECONDS.sleep(50);
}catch(InterruptedException igonre){}
}
public abstract void increment();
}
class PairManager1 extends PairManager
{
@Override
public synchronized void increment()
{
p.incrementsX();
p.incrementsY();
store(getPair());
}
}
class PairManager2 extends PairManager
{
public void increment()
{
Pair temp;
synchronized(this)
{
p.incrementsX();
p.incrementsY();
temp = getPair();
}
store(temp);
}
}
class PairManipulator implements Runnable
{
private PairManager pm;
public PairManipulator(PairManager pm)
{
this.pm = pm;
}
public void run()
{
while(true)
{
pm.increment();
}
}
@Override
public String toString()
{
return "Pair: " + pm.getPair() +
" checkCounter = " + pm.checkCounter.get();
}
}
class PairChecker implements Runnable
{
private PairManager pm;
public PairChecker(PairManager pm)
{
this.pm = pm;
}
public void run()
{
while(true)
{
pm.checkCounter.incrementAndGet();
pm.getPair().checkState();
}
}
}
public class CriticalSection
{
static void testApproaches(PairManager pmna1,PairManager pmna2)
{
ExecutorService exec = Executors.newCachedThreadPool();
PairManipulator
pm1 = new PairManipulator(pmna1),
pm2 = new PairManipulator(pmna2);
PairChecker
pcheck1 = new PairChecker(pmna1),
pcheck2 = new PairChecker(pmna2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try
{
TimeUnit.MILLISECONDS.sleep(500);
}catch(InterruptedException e)
{
System.out.println("Sleep interrupted");
}
System.out.println("pm1 : " + pm1 + "\npm2: " + pm2);
System.exit(0);
}
public static void main(String args[])
{
PairManager
pman1 = new PairManager1(),
pman2 = new PairManager2();
testApproaches(pman1, pman2);
}
}