同时执行两个同步方法
我有4种方法(m1
,m2
,m3
和m4
)在一个类中。方法m1
,m2
和m3
是方法。另外,我有4个线程分别为t1
,t2
,t3
和t4
。同时执行两个同步方法
如果t1
接入m1
方法(同步方式),可以t2
线程访问m2
方法同时(同步方法)?如果不是什么状态的t2?
如果t1访问m1方法(同步方法),可能t2线程同时访问m2方法(同步方法)吗?
的关键字适用于对象级别,只有一个线程可持有对象的锁。所以只要你在谈论同一个对象,那么否,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
如果方法在同一监视器上同步,则它们不能同时在不同的线程中执行。当第二个线程进入监视器条目(这种情况下,同步方法的开始)时,它将阻塞,直到第一个线程释放监视器。
在这种情况下,被阻塞的线程的实际状态,所报告的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
在我假想命名的情况下)显式显示器,所以不会受到任何例如方法调用被阻止。
不,它不能。这是唯一的一点:不同的线程不能同时做这些事情(你不必同时做同一个线程,因为一个线程根本无法并行执行任何操作)。等待线程的状态是'等待锁定'。 (有足够的现代JVM你其实可以有控制台上显示这种状态下,如果你以正确的方式问。)
如果T1接入M1方法(synchronized方法),可以t2的线程访问M2方法(同步方法)同时?
否。线程t2将等待线程t1释放锁。 在你的同一个例子中,t2可以访问未同步的方法m4。
锁在synchronized方法
每个对象都有一个与之关联的内部锁。按照惯例,需要独占且一致地访问对象字段的线程在访问它们之前必须获取对象的内部锁,然后在完成对象的内部锁之后释放固有锁
当线程调用同步方法时,自动获取该方法对象的内部锁并在方法返回时释放它。锁定解除即使返回被一个未捕获的异常
回来到您的第二个查询导致发生:
如果不是这样,这将是T2的状态?
线程t2处于阻塞状态并等待线程t1释放锁。
从Java documentation页:
使方法有两个作用。
首先,对同一对象上的同步方法的两次调用是不可能交错的。当一个线程正在执行一个对象的同步方法时,所有其他线程调用同一对象的同步方法块(挂起执行),直到第一个线程完成对象。其次,当一个同步方法退出时,它会自动建立一个与先前关联的同步对象的任何后续调用同步方法。这保证了所有线程都可以看到对象状态的变化
但是如果我们做这样的事情,那又怎样? final Test tt1 = new Test(); final Test tt2 = new Test();线程t1 = new Thread(){public void run(){tt1.m1(); }};线程t2 = new Thread(){public void run(){tt2.m2(); }}; – Prem 2012-04-10 09:17:50
我运行同样的东西,我得到TIMED_WAIT作为输出.... – Prem 2012-04-10 09:18:12
@aioobe在同步代码块(而不是方法)的情况下会发生什么。两个线程可以同时访问同一对象的两个不同的同步代码块吗? – yuva 2014-09-18 11:48:15