Java 两个同步方法是否同时执行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3160023/
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-13 16:57:08  来源:igfitidea点击:

Do two synchronized methods execute simultaneously

javamultithreadingsynchronized

提问by Tony

I have 4 methods (m1, m2, m3and m4) in a class. Method m1, m2and m3are synchronizedmethods. Also, I have 4 threads t1, t2, t3and t4respectively.

我有4种方法(m1m2m3m4一类)。方法m1m2m3synchronized方法。另外,我有4个线程t1t2t3t4分别。

If t1access the m1method (synchronized method), could t2thread access m2method (synchronized method) simultaneously? If not what would be the state of t2?

如果t1访问m1方法(同步方法),t2线程是否可以m2同时访问方法(同步方法)?如果不是,t2 的状态是什么?

采纳答案by aioobe

If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?

如果t1访问m1方法(同步方法),t2线程是否可以同时访问m2方法(同步方法)?

The synchronizedkeyword applies on object level, and only one thread can hold the lock of the object. So as long as you're talking about the same object, then no, t2will wait for t1to release the lock acquired when it entered m1.

synchronized关键字应用于对象级别,只有一个线程可以持有对象的锁。所以只要你在谈论同一个对象,那么没有t2将等待t1释放,当它进入获得锁m1

The thread can however release the lock without returning from the method, by calling Object.wait().

然而,线程可以通过调用Object.wait().

If not, what would be the state of t2 ?

如果不是, t2 的状态是什么?

It would sit tight and wait for t1to release the lock (return from the method or invoke Object.wait()). Specifically, it will be in a BLOCKEDstate.

它会坐等t1释放锁(从方法返回或调用Object.wait())。具体来说,它将处于一种BLOCKED状态

Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.

线程阻塞等待监视器锁的线程状态。处于阻塞状态的线程正在等待监视器锁进入同步块/方法或调用后重新进入同步块/方法Object.wait

Sample code:

示例代码:

public class Test {

    public synchronized void m1() {
        try { Thread.sleep(2000); }
        catch (InterruptedException ie) {}
    }

    public synchronized void m2() {
        try { Thread.sleep(2000); }
        catch (InterruptedException ie) {}
    }

    public static void main(String[] args) throws InterruptedException {
        final Test t = new Test();
        Thread t1 = new Thread() { public void run() { t.m1(); } };
        Thread t2 = new Thread() { public void run() { t.m2(); } };

        t1.start();
        Thread.sleep(500);

        t2.start();
        Thread.sleep(500);

        System.out.println(t2.getState());
    }
}

Output:

输出:

BLOCKED

回答by Andrzej Doyle

If the methods are synchronized on the same monitor, then they cannot execute simultaneously in different threads. When the second thread comes to the monitor entry (the start of the synchronized method in this case), it will block until the first thread releases the monitor.

如果方法在同一个监视器上同步,则它们不能在不同的线程中同时执行。当第二个线程到达监视器入口时(在这种情况下是同步方法的开始),它将阻塞,直到第一个线程释放监视器。

The actual state of the blocked thread in this case, as reported by jconsole, will be something like java.lang.Thread.State: WAITING (on object monitor)

在这种情况下,被阻塞线程的实际状态,如 jconsole 所报告的,将类似于 java.lang.Thread.State: WAITING (on object monitor)

Assuming all methods are normal instance methods, then they will share the same monitor when invoked on the same object. That is, if you had something like:

假设所有方法都是普通的实例方法,那么它们在同一个对象上调用时将共享同一个监视器。也就是说,如果你有类似的东西:

// Thread 1
A a1 = new A();
a1.m1();

// Thread 2
A a2 = new A();
a2.m2()

then in this case, the second thread will be able to call the method, because it's trying to obtain the implicit monitor of the a2object, which is notlocked by thread 1. But if thread 2 tried to call a1.m2(), then it would block until thread 1 had finished executing m1().

那么在这种情况下,第二个线程将能够调用该方法,因为它正在尝试获取a2对象的隐式监视器,该对象未被线程 1 锁定。但是如果线程 2 尝试调用a1.m2(),那么它将阻塞直到线程1 执行完毕m1()

If you have static methods, then they obtain the explicit monitor of the class itself (A.classin my hypothetical-naming case), so will not be blocked by anyinstance method invocations.

如果您有静态方法,那么它们会获得类本身的显式监视器(A.class在我假设的命名情况下),因此不会被任何实例方法调用阻止。

回答by Kilian Foth

No, it couldn't. That's the only point there is to synchronized: different threads can't do these things simultaneously (You don't have to guard against the same thread doing them simultaneously, because a single thread can't do anything in parallel at all.) The state of the waiting thread is 'waiting for lock'. (With a sufficiently modern JVM you can actually have this state displayed on the console if you ask in the right way.)

不,不能。这是唯一的一点synchronized:不同的线程不能同时做这些事情(你不必防止同一个线程同时做这些事情,因为单个线程根本不能并行做任何事情。)状态等待线程是“等待锁定”。(使用足够现代的 JVM,如果您以正确的方式询问,您实际上可以在控制台上显示此状态。)

回答by Aditya W

If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?

如果t1访问m1方法(同步方法),t2线程是否可以同时访问m2方法(同步方法)?

No. Thread t2 will wait for Thread t1 to release the lock. In your same example, t2 can access method m4 which is not synchronized.

否。线程 t2 将等待线程 t1 释放锁。在您的同一个示例中,t2 可以访问未同步的方法 m4。

Locks In synchronizedMethods

同步方法中的锁

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception

每个对象都有一个与之关联的内在锁。按照惯例,需要对对象字段进行独占且一致访问的线程必须在访问对象之前获取对象的内在锁,然后在访问完成后释放内在锁

当线程调用同步方法时,它会自动获取该方法对象的内在锁,并在该方法返回时释放它。即使返回是由未捕获的异常引起的,也会发生锁释放

Coming back to your second query:

回到你的第二个查询:

If not, what would be the state of t2 ?

如果不是, t2 的状态是什么?

Thread t2 is in blocked state and waiting for Thread t1 to release the lock.

线程 t2 处于阻塞状态,等待线程 t1 释放锁。

From java documentationpage:

从java文档页面:

making synchronizedmethod have two effects.

制作synchronized方法有两个作用。

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 thread

首先,对同一对象的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他调用同一对象的同步方法的线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。

其次,当一个同步方法退出时,它会自动建立一个发生在同一个对象的同步方法的任何后续调用之前的关系。这保证了对象状态的变化对所有线程都是可见的