Concurrent Programming in Java 才翻5页就充满疑惑的代码,大家帮忙分析分析

书上说这段代码解决了并发问题:但我横看竖看还是有问题呀:


import java.util.Random;

class Particle{
protected int x;
protected int y;
protected final Random rng = new Random();

public Particle(int inX,int inY){
x = inX;
y = inY;
}

public synchronized void move(){
x += rng.nextInt(10) - 5 ;
y += rng.nextInt(20) - 10;
}

public void draw(Graphics g){
int lx,ly;
synchronized (this) {lx=x;ly=y;}
g.drawRect(lx,ly,10,10);
}
}

1、由于 move() 与 draw(Graphics g) 方法可能会被两个线程同时调用,那它还是没有解决,“当draw操作使用move方法调用前的y值和move方法调用后的x值绘制一个例子的图形”。

2、protected final Random rng = new Random(); 为什么定义为final?好处具体表现在什么地方?

> 1、由于 move() 与 draw(Graphics g)
> 方法可能会被两个线程同时调用,那它还是没有解决,“当dr
> w操作使用move方法调用前的y值和move方法调用后的x值绘制?> 个例子的图形”。

不太明白这段程序要解决的是哪方面的并发,“当draw操作使用move方法调用前的y值和move方法调用后的x值绘制一个例子的图形”。这句话让人不太理解。

>
> 2、protected final Random rng = new Random();
> 为什么定义为final?好处具体表现在什么地方?

个人理解为:定义为final是为了强制让Particle类的一个实例中只能使用一个rng引用,不允许被转移引用指针,也不允许被null,直到该Particle实例被释放时rng引用才被释放掉. 这么做的目的主要是为了程序逻辑上的安全,当然如果你的记忆力比较好,或者你不想多为将来接受这个程序的人做奉献,要不要final都是一样的.

不好意思,写错两个字
“当draw操作使用move方法调用前的y值和move方法调用后的x值绘制一个粒子的图形”。

这儿的并发问题是,若move方法和draw方法同时被连个线程调用。

有可能发现这样的现象:

1、draw 准备绘图时,先获取一个X,
2、同时,move,修改了 x,y的值
4、draw 获取Y,这是获取的X,Y不是一致性的。 只会在一个错误的点显示一个图形。

所以说“当draw操作使用 move方法调用前的y值和move方法调用后的x值绘制一个粒子的图形”。

不好意思,写错两个字
“当draw操作使用move方法调用前的y值和move方法调用后的x值绘制一个粒子的图形”。

这儿的并发问题是,若move方法和draw方法同时被两个线程调用。

有可能发现这样的现象:

1、draw 准备绘图时,先获取一个X,
2、同时,move,修改了 x,y的值
4、draw 获取Y,这是获取的X,Y不是一致性的。 只会在一个错误的点显示一个图形。

所以说“当draw操作使用 move方法调用前的y值和move方法调用后的x值绘制一个粒子的图形”。

你的担心是多余的:


synchronized (this) {lx=x;ly=y;}

这里上的对象锁,锁定对象是this,所以在此锁定的工作区域里面操作的时候是不允许其它线程move()的,直到该锁定区域运行完毕,这时候this实例上的对象锁就被释放掉了.move()操作就可以被执行了.

而在move()动作上有一个方法锁,在此方法操作的时候是不允许x值和y值被两个线程乱改的.

因为在写的时候x,y是一致的,而在读的时候该x,y又不允许被修改,所以说它解决了你所担心的这个并发问题

谢谢!
多线程我要补补课啦 :)

那我要想问个问题,下面的代码:


public class QueueThread extends Thread {

private static Logger logger = Logger.getLogger(QueueThread.class.getName());

private PacketQueue packetQueue;
private HashMap packetListeners = new HashMap();

public QueueThread(PacketQueue queue) { packetQueue = queue; }

public boolean addListener(PacketListener listener, String element){
if (listener == null || element == null){
return false;
}
packetListeners.put(listener,element);
return true;
}

public boolean removeListener(PacketListener listener){
packetListeners.remove(listener);
return true;
}

public void run(){

for( Packet packet = packetQueue.pull();
packet != null;
packet = packetQueue.pull()) {

logger.finest("Get One Packet:" + packet);
try {
Packet child;
String matchString;
if (packet.getElement().equals(
"iq")){
child = packet.getFirstChild(
"query");
if (child == null){
matchString =
"iq";
} else {
matchString = child.getNamespace();
}
} else {
matchString = packet.getElement();
}

synchronized(packetListeners){
Iterator iter = packetListeners.keySet().iterator();
while (iter.hasNext()){
PacketListener listener = (PacketListener)iter.next();
String listenerString = (String)packetListeners.get(listener);
if (listenerString.equals(matchString)){
listener.notify(packet);
}
}
}
} catch (Exception ex){
//Log.error("QueueThread: ", ex); // Soldier on - no matter what
}
}
}
}

一旦任意线程进入


synchronized(packetListeners){
Iterator iter = packetListeners.keySet().iterator();
while (iter.hasNext()){
PacketListener listener = (PacketListener)iter.next();
String listenerString = (String)packetListeners.get(listener);
if (listenerString.equals(matchString)){
listener.notify(packet);
}
}
}

代码块,则别的线程调用函数

public boolean addListener(PacketListener listener, String element){
if (listener == null || element == null){
return false;
}
packetListeners.put(listener,element);
return true;
}

执行到
packetListeners.put(listener,element);
处一定是阻塞状态对不?