如何正确同步/锁定变量



我在理解Java中的synchronized(){}时遇到问题。不知怎的,我认为synchronized(this)我锁定了类的this实例,如果我想从另一个线程访问属性或调用这个特定实例的函数,那么这个其他线程必须等到synchronizeds结束。不知怎么的,在这个示例代码中它不起作用。我希望线程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一直在读取。

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

您对synchronize的作用有错误的理解,它不是锁定您使用的对象,而是将该对象用作锁定一段可执行代码的信号量。你的例子:

synchronized (this){
loaded = true;
}

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

您的问题更多的是一个线程如何等待并被通知其他线程中的事件。有很多不同的技术可以做到这一点。现代的方法(java8)是使用CompletableFuture。另一个更为java根源的方法是wait()和notify(),这两个方法都是每个Object(及其派生)都知道的方法。我在这个SO答案中提供了后者的一个简单例子

最新更新