Java同步方法

考虑这个代码:

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

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

如果'synchronized'locking只能访问此方法或访问此方法中使用的所有对象,则无法在任何位置find。

Solutions Collecting From Web of "Java同步方法"

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

 synchronized AnyType foobar(...) { doSomething(); } 

不过是写这个的捷径:

 AnyType foobar(...) { synchronized(this) { doSomething(); } } 

这两种方法都没有什么特别之处。 什么是特别的是同步 ,什么同步块做很简单。 当JVM执行这个时:

 synchronized(foo) { doSomething(); } 

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

locking是什么意思? 这可能意味着比你想象的要less。 它不会阻止其他线程使用该对象。 它不会阻止他们访问对象的字段或更新其字段。 locking对象所阻止的唯一事情是,它可以防止其他线程同时locking相同的对象。

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


您使用synchronized块来保护数据

假设你的程序有一些可以处于不同状态的对象集合。 假设有些国家是有道理的,但也有其他国家没有意义的无效国家。

假设一个线程不可能将数据从一个有效状态改变为另一个有效状态而不暂时创build一个无效状态。

如果你把改变状态的代码放到一个synchronized(foo)块中,并且把每个可以看到状态的代码块放到一个locking同一个对象 foo的同步块中,那么你将阻止其他线程看到暂时无效的状态。

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

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

  • 首先,同一个对象上的两个同步方法的调用是不可能交错的。 当一个线程正在执行一个对象的同步方法时,所有其他调用同一对象的同步方法的线程将阻塞(挂起执行),直到第一个线程完成对象。
  • 其次,当一个同步的方法退出时,它会自动build立一个与先前同步对象的任何后续调用同步方法的before-before关系。 这保证了对所有线程都可见的对象状态的改变。 请注意,构造函数不能同步 – 在构造函数中使用synchronized关键字是一个语法错误。 同步构造函数没有意义,因为只有创build对象的线程在构build时才能访问它。

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