Java同步方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31652489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:22:21  来源:igfitidea点击:

Java synchronized method

javaandroidmultithreadingthread-safetydeadlock

提问by arenaq

Consider this code:

考虑这个代码:

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

I've got simple question: When Thread 1 calls onSignalsTimeout method, can Thread 2 access objects that are accessed in that method?

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

Can't find anywhere if 'synchronized' locks only access to this method or access to all objects used in this method.

如果“同步”锁定仅访问此方法或访问此方法中使用的所有对象,则找不到任何地方。

采纳答案by Solomon Slow

First of all, forget about synchronized methods. A so-called synchronized method...

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

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

Is nothing but a shortcut way of writing this:

只不过是写这个的快捷方式:

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

There is nothing special about the methodin either case. What is special is the synchronized block, and what a synchronized block does is very simple. When the JVM executes this:

在这两种情况下,该方法都没有什么特别之处。特殊的是同步,同步块所做的非常简单。当 JVM 执行此操作时:

synchronized(foo) {
    doSomething();
}

It first evaluates the expression foo. The result must be an object reference. Then it locks the object, performs the body of the synchronizedblock, and then it unlocks the object.

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

But what does lockedmean? It may mean less than you think. It does notprevent other threads from using the object. It doesn't prevent them from accessing the object's fields or, from updating its fields. The only thing that locking an object prevents is, it prevents other threads from locking the same object at the same time.

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

If thread A tries to enter synchronized(foo) {...}while thread B already has foo locked (either in the same synchronizedblock, or in a different one), then thread A will be forced to wait until thread B releases the lock.

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



You use synchronizedblocks to protect data.

您使用synchronized块来保护数据

Suppose your program has some collection of objects that can be in different states. Suppose that some states make sense, but there are other states that don't make sense—invalidstates.

假设您的程序有一些可以处于不同状态的对象集合。假设某些状态有意义,但还有其他状态没有意义——无效状态。

Suppose that it is not possible for a thread to change the data from one valid state to another valid state without temporarilycreating an invalid state.

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

If you put the code that changes the state in a synchronized(foo)block, and you put everyblock of code that can seethe state into a synchronized block that locks the same object, foo, then you will prevent other threads from seeing the temporary invalid state.

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

回答by Bathsheba

In this context, synchronizedsimultaneously locks this method and any other method similarly marked as synchronizedin your class.

在此上下文中,synchronized同时锁定此方法和与synchronized您的类中类似标记的任何其他方法。

回答by Andrea Iacono

Yes, other threads can access the objects used in the method; the synchronized keyword guarantees that no more than one thread at the time can execute the code of the method.

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

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

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

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads. Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.
  • 首先,对同一对象的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他调用同一个对象的同步方法的线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。
  • 其次,当一个同步方法退出时,它会自动建立一个发生在同一个对象的同步方法的任何后续调用之前的关系。这保证了对象状态的更改对所有线程都是可见的。请注意,构造函数不能同步——在构造函数中使用 synchronized 关键字是一个语法错误。同步构造函数没有意义,因为只有创建对象的线程才能在构造对象时访问它。