同步问题 thinking in java中的一段代码 不知如何理解
P494
同步控制块必须指定一个对象才能进行同步,通常,最合理的对象就是在其上调用方法的当前对象: synchronized(this),在PairManager2中采用了这种方法。这样,当为同步控制块请求锁的时候,对象的其它同步控制方法就不能被调用了。所以其效
果不过是缩小了同步控制的范围。
但是随后就给了一段代码:
//: c13:SyncObject.java
// Synchronizing on another object
// From 'Thinking in Java, 3rd ed. ' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
import com.bruceeckel.simpletest.*;
class DualSynch {
private Object syncObject = new Object();
public synchronized void f() {
System.out.println( "Inside f() ");
// Doesn 't release lock:
try {
Thread.sleep(500);
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println( "Leaving f() ");
}
public void g() {
synchronized(syncObject) {
System.out.println( "Inside g() ");
try {
Thread.sleep(500);
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println( "Leaving g() ");
}
}
}
public class SyncObject {
private static Test monitor = new Test();
public static void main(String[] args) {
final DualSynch ds = new DualSynch();
new Thread() {
public void run() {
ds.f();
}
}.start();
ds.g();
monitor.expect(new String[] {
"Inside g() ",
"Inside f() ",
"Leaving g() ",
"Leaving f() "
}, Test.WAIT + Test.IGNORE_ORDER);
}
} ///:~
这里两种同步方法都用到了 但结果并不是 "这样,当为同步控制块请求锁的时候,对象的其它同步控制方法就不能被调用了 "
第一段文字针对的是下面的代码:
//: c13:CriticalSection.java
// Synchronizing blocks instead of entire methods. Also
// demonstrates protection of a non-thread-safe class
// with a thread-safe one.
// From 'Thinking in Java, 3rd ed. ' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
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
}
} ///:~
请问 第一段文字如何理解 ?? 谢谢 !
[解决办法]
帮顶
[解决办法]
不清楚楼主是哪里不明白,synchronized 字段可以加在方法前面如
public synchronized void get(){
.......
}
就相当于
public void get(){
synchronized(this){
.......
}
}
楼主贴出的上半段代码f()和g()虽然都有synchronized 字段,但是两者加锁的对象却不一致,一个是this,而另一个是syncObject ;这两个方法当然不会造成互斥访问了