鉴于下面提到的代码并假设我们有两个不同的线程thread1,thread2以及类BCell的两个不同的对象p1和p2。
如果 thread1 执行p1.swap(p2)
而 thread2 同时执行p2.swap(p1)
可能会出现什么问题?
我已经阅读了here和here,但它似乎没有帮助。
class BCell {
int value;
public synchronized int getValue() {
return value;
}
public synchronized void setValue(int i) {
value=i;
}
public synchronized void swap(BCell x) {
int temp = getValue();
setValue(x.getValue);
x.setValue(temp);
}
}
答案 0 :(得分:2)
这是一个同步的实例方法:
public synchronized void add(int value){ this.count += value; }
请注意在方法声明中使用synchronized关键字。 这告诉Java该方法是同步的。
Java中的同步实例方法在 实例(对象)拥有该方法。
报价来源为here。
这意味着当您调用p1.swap(p2)
时,它会阻止p1
在该实例上的任何其他同步块中使用,直到p1.swap(p2)
完成。因此,在您的情况下,setValue(x.getValue);
无法同时调用。
答案 1 :(得分:1)
p1和p2是两个不同的实例。因此,即使方法不同步,也不应出现竞争条件。
请注意,这三个是实例方法,并且您在实例锁上进行同步。 p1和p2也是两个不同的实例。因此,在这种情况下,您提出的同步方法不会发生任何变化。
答案 2 :(得分:0)
可能的问题是p1和p2都得到相同的值。如果t1在读取任何内容之前t1一直执行到setValue(x.getValue());
会导致此问题,例如val1 = 5
和val2 = 3
(根据线程定义变量,希望它有意义)
val1 = 5 val2 = 3
tmp1 = 5
val1 = 3
tmp2 = 3
val2 = 3
val2 = 3
val1 = 3
其中thread1位于第一列,thread2位于第二列。
也许你可以写这样的东西?
class BCell {
Semaphore writeLock = new Semaphore(1);
int value;
public int getValue() {
return value;
}
public void setValue(int i) throws InterruptedException {
writeLock.acquire();
value=i;
writeLock.release();
}
public void swap(BCell x) throws InterruptedException {
writeLock.acquire();
if(x.writeLock.tryAcquire(10, TimeUnit.MILLISECONDS)) {
int temp = getValue();
setValue(x.getValue());
x.setValue(temp);
x.writeLock.release();
}
else {
writeLock.release();
swap(x);
}
writeLock.release();
}
}