Java线程-同步Don

时间:2018-06-22 15:08:23

标签: multithreading locking synchronized

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”。

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);
            }

        }
    }

}