我在一个类中有4个方法(m1
,m2
,m3
和m4
)。方法m1
,m2
和m3
是synchronized
方法。另外,我分别有4个帖子t1
,t2
,t3
和t4
。
如果t1
访问m1
方法(synchronized方法),可以同时t2
线程访问m2
方法(同步方法)吗?如果不是t2的状态是什么?
答案 0 :(得分:44)
如果t1访问m1方法(同步方法),可以同时t2线程访问m2方法(同步方法)吗?
synchronized
关键字适用于对象级别,只有一个线程可以保存对象的锁定。因此,只要您谈论同一个对象,然后没有,t2
将等待t1
释放进入m1
时获取的锁定。
然而,线程可以通过调用Object.wait()
来释放锁而不从方法返回。
如果没有,那么t2的状态是什么?
它会坐下来等待t1
释放锁(从方法返回或调用Object.wait()
)。具体来说,它将在BLOCKED
state。
线程阻塞等待监视器锁定的线程状态。处于阻塞状态的线程正在等待监视器锁定以在调用
Object.wait
后输入同步块/方法或重新输入同步块/方法。
示例代码:
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());
}
}
<强>输出:强>
BLOCKED
答案 1 :(得分:11)
如果方法在同一监视器上同步,则它们不能在不同的线程中同时执行。当第二个线程进入监视器条目(在这种情况下是同步方法的开始)时,它将阻塞,直到第一个线程释放监视器。
在这种情况下,由jconsole报告的阻塞线程的实际状态将类似于java.lang.Thread.State: WAITING (on object monitor)
假设所有方法都是普通的实例方法,那么它们将在同一个对象上调用时共享同一个监视器。也就是说,如果你有类似的东西:
// Thread 1
A a1 = new A();
a1.m1();
// Thread 2
A a2 = new A();
a2.m2()
然后在这种情况下,第二个线程将能够调用该方法,因为它正在尝试获取a2
对象的隐式监视器,该对象不被线程1锁定但是如果线程2试图调用a1.m2()
,那么它将阻塞,直到线程1完成执行m1()
。
如果您有静态方法,那么它们会获得类本身的显式监视器(在我的假设命名情况下为A.class
),因此不会被任何实例方法调用阻止
答案 2 :(得分:4)
不,它不能。这是synchronized
的唯一要点:不同的线程不能同时执行这些操作(您不必防止同时执行这些操作的线程,因为单个线程无法并行执行任何操作所有。)等待线程的状态是“等待锁定”。 (如果您以正确的方式提问,使用足够现代的JVM,您实际上可以在控制台上显示此状态。)
答案 3 :(得分:1)
如果t1访问m1方法(同步方法),可以同时进行t2线程访问m2方法(同步方法)吗?
没有。线程t2将等待线程t1释放锁定。 在同一个例子中,t2可以访问未同步的方法m4。
锁定synchronized方法
每个对象都有一个与之关联的内在锁。按照惯例,需要对对象字段进行独占和一致访问的线程必须在访问对象之前获取对象的内部锁,然后在它们完成时释放内部锁< / p>
当线程调用synchronized方法时,它会自动获取该方法对象的内部锁,并在方法返回时释放它。即使返回是由未捕获的异常引起的,也会发生锁定释放
回到第二个问题:
如果没有,那么t2的状态是什么?
线程t2处于阻塞状态并等待线程t1释放锁定。
来自java documentation页面:
制作synchronized
方法有两个效果。
首先,对同一对象的两个同步方法的调用不可能进行交错。当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法阻塞(暂停执行),直到第一个线程完成对象为止。
其次,当synchronized方法退出时,它会自动与同一对象的同步方法的任何后续调用建立一个before-before关系。这可以保证对所有线程
都可以看到对象状态的更改