import java.util.*;class Pair { // Not thread-safe
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;
}
public class PairValuesNotEqualException
extends RuntimeException {
public PairValuesNotEqualException() {
super("Pair values not equal: " + Pair.this);
}
}
// Arbitrary invariant -- both variables must be equal:
public void checkState() {
if(x != y)
throw new PairValuesNotEqualException();
}
}// Protect a Pair inside a thread-safe class:
abstract class PairManager {
protected Pair p = new Pair();
private List storage = new ArrayList();
public synchronized Pair getPair() {
// Make a copy to keep the original safe:
return new Pair(p.getX(), p.getY());
}
protected void store() { storage.add(getPair()); }
// A "template method":
public abstract void doTask();
}// Synchronize the entire method:
class PairManager1 extends PairManager {
public synchronized void doTask() {
p.incrementX();
p.incrementY();
store();
}
}// Use a critical section:
class PairManager2 extends PairManager {
public void doTask() {
synchronized(this) {
p.incrementX();
p.incrementY();
}
store();
}
}class PairManipulator extends Thread {
private PairManager pm;
private int checkCounter = 0;
private class PairChecker extends Thread {
PairChecker() { start(); }
public void run() {
while(true) {
checkCounter++;
pm.getPair().checkState();
}
}
}
public PairManipulator(PairManager pm) {
this.pm = pm;
start();
new PairChecker();
}
public void run() {
while(true) {
pm.doTask();
}
}
public String toString() {
return "Pair: " + pm.getPair() +
" checkCounter = " + checkCounter;
}
}public class CriticalSection {
public static void main(String[] args) {
// Test the two different approaches:
final PairManipulator
pm1 = new PairManipulator(new PairManager1()),
pm2 = new PairManipulator(new PairManager2());
new Timer(true).schedule(new TimerTask() {
public void run() {
System.out.println("pm1: " + pm1);
System.out.println("pm2: " + pm2);
System.exit(0);
}
}, 500); // run() after 500 milliseconds
}
} ///:~我测试的输出结果是
pm1: Pair: x: 373845, y: 373845 checkCounter = 68832
pm2: Pair: x: 133935, y: 133935 checkCounter = 549925几个弱智问题
1.执行 start(); new PairChecker(); 后,doTask中对x,y的递增和PairChecker 线程中checkCounter的递增几乎同时开始的啊,两个线程优先级也一样,为啥最后checkCounter 比x和y少那么多???2.为什么pm2的x,y比pm1的x,y少, 而checkCounter 比Pm1的checkCounter 多很多呢?
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;
}
public class PairValuesNotEqualException
extends RuntimeException {
public PairValuesNotEqualException() {
super("Pair values not equal: " + Pair.this);
}
}
// Arbitrary invariant -- both variables must be equal:
public void checkState() {
if(x != y)
throw new PairValuesNotEqualException();
}
}// Protect a Pair inside a thread-safe class:
abstract class PairManager {
protected Pair p = new Pair();
private List storage = new ArrayList();
public synchronized Pair getPair() {
// Make a copy to keep the original safe:
return new Pair(p.getX(), p.getY());
}
protected void store() { storage.add(getPair()); }
// A "template method":
public abstract void doTask();
}// Synchronize the entire method:
class PairManager1 extends PairManager {
public synchronized void doTask() {
p.incrementX();
p.incrementY();
store();
}
}// Use a critical section:
class PairManager2 extends PairManager {
public void doTask() {
synchronized(this) {
p.incrementX();
p.incrementY();
}
store();
}
}class PairManipulator extends Thread {
private PairManager pm;
private int checkCounter = 0;
private class PairChecker extends Thread {
PairChecker() { start(); }
public void run() {
while(true) {
checkCounter++;
pm.getPair().checkState();
}
}
}
public PairManipulator(PairManager pm) {
this.pm = pm;
start();
new PairChecker();
}
public void run() {
while(true) {
pm.doTask();
}
}
public String toString() {
return "Pair: " + pm.getPair() +
" checkCounter = " + checkCounter;
}
}public class CriticalSection {
public static void main(String[] args) {
// Test the two different approaches:
final PairManipulator
pm1 = new PairManipulator(new PairManager1()),
pm2 = new PairManipulator(new PairManager2());
new Timer(true).schedule(new TimerTask() {
public void run() {
System.out.println("pm1: " + pm1);
System.out.println("pm2: " + pm2);
System.exit(0);
}
}, 500); // run() after 500 milliseconds
}
} ///:~我测试的输出结果是
pm1: Pair: x: 373845, y: 373845 checkCounter = 68832
pm2: Pair: x: 133935, y: 133935 checkCounter = 549925几个弱智问题
1.执行 start(); new PairChecker(); 后,doTask中对x,y的递增和PairChecker 线程中checkCounter的递增几乎同时开始的啊,两个线程优先级也一样,为啥最后checkCounter 比x和y少那么多???2.为什么pm2的x,y比pm1的x,y少, 而checkCounter 比Pm1的checkCounter 多很多呢?
能否具体点啊,对于pm1而言。 doTask中内容的运行时间难道比PairChecker线程的更快,以至于运行了更多次?