我们有这种情况
class Pole extends Thread
{
JButton pole;
Plansza p;
Pole neighbours[] = new Pole[4];
public Pole(Plansza p)
{
this.p = p;
pole = new JButton();
int r,g,b;
r=p.rndColor();
g=p.rndColor();
b=p.rndColor();
pole.setBackground(new Color(r,g,b));
}
public Pole()
{
;
}
public void run()
{
while(true)
{
Thread.yield();
try
{
Thread.sleep((int)p.rndTime());
}
catch(InterruptedException e)
{
;
}
if(p.rnd.nextDouble()<=1-p.p)
setNeighboursColor();
if(p.rnd.nextDouble()<=p.p)
setRandomColor();
}
}
public void setRandomColor()
{
synchronized(this)
{
int r,g,b;
r = p.rndColor();
g = p.rndColor();
b = p.rndColor();
pole.setBackground(new Color(r,g,b));
}
}
public void setNeighboursColor()
{
synchronized(this)
{
int r,g,b;
Color c0 = neighbours[0].pole.getBackground();
Color c1 = neighbours[1].pole.getBackground();
Color c2 = neighbours[2].pole.getBackground();
Color c3 = neighbours[3].pole.getBackground();
r = (int)(c0.getRed() + c1.getRed() + c2.getRed() + c3.getRed())/4;
g = (int)(c0.getGreen() + c1.getGreen() + c2.getGreen() + c3.getGreen())/4;
b = (int)(c0.getBlue() + c1.getBlue() + c2.getBlue() + c3.getBlue())/4;
Color nc = new Color(r,g,b);
pole.setBackground(nc);
}
}
}
我编辑了问题并粘贴了我的代码,所以也许现在它有点清晰了 每个Pole(Field)与其他4个Pole对象存在邻居关系,因此我们有很多这样的对象,每个都是不同的线程,它们可以从邻居中读取颜色,并将其自身颜色更改为邻居颜色的算术平均值。
答案 0 :(得分:3)
没有任何意义,我认为你对Java中的同步工作方式完全错误。
无法在Java中“锁定对象”。你的问题并不完全清楚,因为X
正在进行奇怪的无限嵌套,所以x[1]
是模棱两可的。但实质是如果一个对象试图分配或读取另一个对象的字段,它将成功读/写。它可以等待的唯一方法是预先选择在监视器上同步。 (这种等待当然可以封装,例如c
是AtomicReference<Color>
或类似的 - 不必明确地完成。)
此外,如果涉及多个线程,则可见性也成为问题。您必须将X
数组以及Color
变量声明为volatile
,否则无法保证其他线程可以看到更新。或者,如果您确实选择沿着同步路线前进,并且始终如一地执行此操作,那么也可以保证可见性(尽管听起来并不符合您的想法)。
我不完全确定你在这里尝试的是什么,所以不能给出任何设计建议。但我建议使用Java Concurrency In Practice一书。并发性是 hard ,如果你想避免微妙的错误,必须要抓住它。与其他任何发展领域相比,它需要事先了解这些原则,而不是仅仅在问题出现时混淆不清。
答案 1 :(得分:2)
Andrzej的回答非常好,你应该按照他的建议行事。我将发布一个简单的解释,让你开始。
如果对象例如x [3]在x [1]时锁定自己将会发生什么 将尝试分配c = x [3] .x?
可能会发生数据竞争。
如果要防止数据争用,则必须确保访问同一变量的所有线程都是同步的,这意味着它们访问它的同步块被锁定在同一个监视器上。
看起来像这样:
Colection col;
Object colLock;
void accessCollectionThread1() {
synchronized(colLock) {
// do stuff with the collection
}
}
void accessCollectionThread2() {
synchronized(colLock) {
// do other stuff with the collection
}
}
这样,两个操作序列将永远不会同时发生,并且不会有数据争用。