public class SetGetFail implements Runnable {
// Every thread is assigned a number and has a reference to a SharedObject.
// In main(), a single SharedObject is passed to all threads.
int number;
SharedObject shared;
public SetGetFail(int no, SharedObject so) {
number = no;
shared = so;
}
public static void main(String[] args) {
SharedObject shared = new SharedObject(0);
new Thread(new SetGetFail(1, shared)).start();
new Thread(new SetGetFail(2, shared)).start();
}
synchronized public void run() {
setGet();
}
synchronized void setGet() {
// Repeatedly assign this thread's own number to the shared
// object and race to read that number again.
// Exit, if some other thread modified the number in between.
while(true) {
shared.setNo(number);
int no = shared.getNo();
if (no != number) {
System.out.println("Thread " + number + " sees " + no);
System.exit(no);
}
}
}}
所以我对代码的问题是,为什么“同步”不阻止这些线程之间的竞争? 当线程1从共享中获取/设置值时,线程2应该被锁定,但是结果仍然是“线程2看到1”。
答案 0 :(得分:0)
像这样更改代码。我添加了一条额外的日志语句,只是为了证明它正在运行。现在让我解释一下这个问题。您刚刚声明了修改共享状态的方法。
synchronized void setGet() {
// ...
}
因此,每个线程都获得自己的锁,并同时修改共享数据。这就是为什么您的线程2看到另一个线程设置的值1的原因。为了保护这一点,您需要使用thread1和thread2实例共有的锁。为此,您需要使用在两个线程之间共享的显式锁对象,并使用该共享锁进行同步。这就是我为解决此问题所做的事情。
private static final Object lock = new Object();
synchronized (lock) {
// ...
}
public class SetGetFail implements Runnable {
// Every thread is assigned a number and has a reference to a SharedObject.
// In main(), a single SharedObject is passed to all threads.
int number;
SharedObject shared;
private static Object lock = new Object();
public SetGetFail(int no, SharedObject so) {
number = no;
shared = so;
}
public static void main(String[] args) throws InterruptedException {
SharedObject shared = new SharedObject(0);
new Thread(new SetGetFail(1, shared), "One").start();
new Thread(new SetGetFail(2, shared), "Two").start();
}
synchronized public void run() {
setGet();
}
void setGet() {
// Repeatedly assign this thread's own number to the shared
// object and race to read that number again.
// Exit, if some other thread modified the number in between.
while (true) {
synchronized (lock) {
shared.setNo(number);
int no = shared.getNo();
if (no != number) {
System.out.println("Thread " + number + " sees " + no);
System.exit(no);
}
System.out.println("Thread " + number + " sees " + no);
}
}
}
}