同步方法是否必须在使用它的 class 外部?
Does a synchronized method have to be external to a class that's using it?
场景一
同步方法是私有的,位于实现 Runnable
的 class 中
Main.java
public class Main {
Thread thread1 = new Thread(new MyRunnable);
. . .
}
MyRunnable.java
public class MyRunnable implements Runnable {
. . .
private synchronized doSomething {
}
场景 2.
同步方法是 public 和静态的,位于 Main class
Main.java
public class Main {
Thread thread1 = new Thread(new MyRunnable);
public synchronized static doSomething() {
}
}
MyRunnable.java
public class MyRunnable implements Runnable {
. . .
}
提问:以上哪个场景是正确的?
我正在关注场景 2。所以我在 Main class 中有一个同步方法。这很好用。当我将此同步方法移至 MyRunnable class 时,我没有发现任何差异。这很奇怪。我原以为它会失败。 synchronized
阻止同时访问此方法。
但是如果我实例化 class 的两个实例:
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
每个可运行对象都有自己的 synchronized
,而 synchronized
对编译器没有任何意义。我理解正确吗?
synchronized
定义 运行时 行为。它在 编译时 .
什么都不做
一个 synchronized
方法被锁定在对象 (this
) 的 实例 上。
static synchronized
方法锁定在对象的 Class
上。
此行为在 JLS §8.4.3.6. synchronized
Methods
中定义
A synchronized method acquires a monitor (§17.1) before it executes.
For a class (static) method, the monitor associated with the Class object for the method's class is used.
For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
因此,在您的场景 1 中,方法针对 MyRunnable
的每个单独实例被锁定,而在 场景 2 中该方法被锁定在 Main.class
对象上(它或多或少是全局的,在相同的 class 加载器下也是如此)。
考虑一下,在*场景 1 中:
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
在这里,t1 和 t2 使用相同的 MyRunnable
实例,这意味着它们将无法并行执行 doSomething()
。
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
在这里,t1 和 t2 可以在 MyRunnable
的实例上执行 doSomething()
他们被并行地,因为他们锁定了实例。
在场景2中,两个线程无法并行执行doSomething()
,因为它们锁定在Main.class
并且被同一个[=26]加载=].
场景一
同步方法是私有的,位于实现 Runnable
的 class 中Main.java
public class Main {
Thread thread1 = new Thread(new MyRunnable);
. . .
}
MyRunnable.java
public class MyRunnable implements Runnable {
. . .
private synchronized doSomething {
}
场景 2.
同步方法是 public 和静态的,位于 Main class
Main.java
public class Main {
Thread thread1 = new Thread(new MyRunnable);
public synchronized static doSomething() {
}
}
MyRunnable.java
public class MyRunnable implements Runnable {
. . .
}
提问:以上哪个场景是正确的?
我正在关注场景 2。所以我在 Main class 中有一个同步方法。这很好用。当我将此同步方法移至 MyRunnable class 时,我没有发现任何差异。这很奇怪。我原以为它会失败。 synchronized
阻止同时访问此方法。
但是如果我实例化 class 的两个实例:
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
每个可运行对象都有自己的 synchronized
,而 synchronized
对编译器没有任何意义。我理解正确吗?
synchronized
定义 运行时 行为。它在 编译时 .
一个 synchronized
方法被锁定在对象 (this
) 的 实例 上。
static synchronized
方法锁定在对象的 Class
上。
此行为在 JLS §8.4.3.6. synchronized
Methods
A synchronized method acquires a monitor (§17.1) before it executes.
For a class (static) method, the monitor associated with the Class object for the method's class is used.
For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
因此,在您的场景 1 中,方法针对 MyRunnable
的每个单独实例被锁定,而在 场景 2 中该方法被锁定在 Main.class
对象上(它或多或少是全局的,在相同的 class 加载器下也是如此)。
考虑一下,在*场景 1 中:
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
在这里,t1 和 t2 使用相同的 MyRunnable
实例,这意味着它们将无法并行执行 doSomething()
。
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
在这里,t1 和 t2 可以在 MyRunnable
的实例上执行 doSomething()
他们被并行地,因为他们锁定了实例。
在场景2中,两个线程无法并行执行doSomething()
,因为它们锁定在Main.class
并且被同一个[=26]加载=].