Java同步方法

are*_*naq 40 java multithreading android deadlock thread-safety

考虑以下代码:

public synchronized void onSignalsTimeout(List<SignalSpec> specs) {
    if (specs != null && specs.size() > 0) {
        for (SignalSpec spec : specs) {
            ParsedCANSignal timeoutedSignal = new ParsedCANSignal();
            SignalsProvider.getInstance().setSignal(spec.name, spec.parent.parent.channel, timeoutedSignal);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个简单的问题:当线程1调用onSignalsTimeout方法时,线程2可以访问在该方法中访问的对象吗?

如果'synchronized'锁只能访问此方法或访问此方法中使用的所有对象,则无法找到任何位置.

Sol*_*low 98

首先,忘记同步方法.一种所谓的同步方法......

synchronized AnyType foobar(...) {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

只不过是写这篇文章的捷径:

AnyType foobar(...) {
    synchronized(this) {
        doSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,该方法都没有什么特别之处.有意义的是同步,同步块的作用非常简单.当JVM执行此操作时:

synchronized(foo) {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

它首先评估表达式foo.结果必须是对象引用.然后它锁定对象,执行synchronized块的主体,然后解锁对象.

锁定是什么意思?这可能意味着比你想象的要少.它并不能阻止其他线程使用的对象.它不会阻止它们访问对象的字段,也不会阻止它们更新其字段.锁定对象唯一阻止的是,它可以防止其他线程同时锁定同一个对象.

如果线程A尝试进入,synchronized(foo) {...}而线程B已经锁定了foo(在同一个synchronized块中,或者在另一个块中),则线程A将被强制等待,直到线程B释放锁定.


您使用synchronized块来保护数据.

假设您的程序有一些可以处于不同状态的对象集合.假设一些国家是有意义的,但也有其他规定,不要让正义- 无效状态.

假设线程无法在不临时创建无效状态的情况下将数据从一个有效状态更改为另一个有效状态.

如果你把一个改变状态的代码synchronized(foo)块,你把每一个代码块,可以看到状态变成一个同步块锁定同一个对象,foo,那么你将阻止其他线程看到临时无效状态.

  • 你的解释非常好,易于理解.由于你进入了更多细节,我必须问......当一个线程锁定对象时,其他线程将被挂起(等待)解锁?我知道它可能是'调试'的问题,但是当我在死锁期间挂起所有线程时我感到很困惑,因为我发现两个线程都执行相同的同步方法 - 我希望一个在开头,一个在另一个同步开始方法(创建一个循环). (4认同)

And*_*ono 8

是的,其他线程可以访问方法中使用的对象; synchronized关键字保证当时只有一个线程可以执行该方法的代码.

来自https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html:

  • 首先,对同一对象的两个同步方法的调用不可能进行交错.当一个线程正在为对象执行同步方法时,所有其他线程调用同一对象的同步方法(暂停执行)直到第一个线程完成对象.
  • 其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立先发生关系.这可以保证对所有线程都可以看到对象状态的更改.请注意,构造函数无法同步 - 将synchronized关键字与构造函数一起使用是一种语法错误.同步构造函数没有意义,因为只有创建对象的线程在构造时才能访问它.


Bat*_*eba 5

在这种情况下,synchronized同时锁定此方法和synchronized类中标记为类似的任何其他方法。