如何正确同步/锁定变量?

How to Synchronizing / Locking a Variable right?

我无法理解 Java 中的 synchronized(){}。不知何故,我认为 synchronized(this) 我锁定了 Class 的 THIS 实例,如果我想访问一个属性或从另一个线程调用这个特定实例的函数,那么另一个线程必须等到 synchronized 结束。不知何故,在此示例代码中它不起作用。 我想让线程 A 等到线程 B 做某事后再继续。

public class A implements Runnable{
public void start(){
    Thread t = new Thread(this);
    t.start();
}
public void run(){
    B b = new B();
    b.start();

    //DO STUFF
    while(b.loaded){
        //WAIT FOR B DOING STUFF
    }

    //GO ON DOING STUFF
}
}

public class B implements Runnable {
public boolean loaded;
public B(){
    loaded = false;
}
public void start(){
    Thread thread = new Thread(this);
    thread.start();
}

public void run(){
    //DOING STUFF
    synchronized (this){
        loaded = true;
    }
    //DO OTHER STUFF
}

}

如果我执行一个名为

的方法,它就会起作用
public synchronized boolean getLoaded(){return loaded;}

但是为什么写和读过程必须同步?如果对象仅在写入时被锁定,那么读取必须等待,这还不够吗?在第一个示例中,我希望编程执行以下操作:

线程 A 正在读取加载的变量。

线程 B 想要写入加载的变量,但它是同步的,所以它锁定了对象。

线程 A 尝试读取加载的变量,但对象被锁定,因此它等待。

线程 B 写入变量。

线程 B 解锁。

线程 A 继续阅读。

我读了很多关于这个话题的书,但我不能 100% 理解它。希望有人能向我解释这个简单的项目。

你对synchronize的作用理解错误,它不是锁定你使用的对象,而是把那个对象当作信号量来锁定一段可执行代码。你的例子:

synchronized (this){
    loaded = true;
}

只锁定一行"loaded = true"。它防止另一个线程可以输入同一行代码。它在 "synchronized(this)" 语句中等待,直到第一个线程(拥有信号量)通过释放信号量离开块。

你的问题更多的是一个线程如何等待和通知其他线程中的事件。有很多不同的技术可以做到这一点。现代的 (java8) 是使用 CompletableFuture。另一个更接近 java 的根源是 wait() 和 notify() 对,它们都是每个对象(及其派生对象)都知道的方法。我在 this SO answer

中提供了后者的一个简单示例