可以说我在类synchronized hi(){}
中有方法synchronized hello(){}
和ABC
方法。两个线程t1
和t2
分别执行t1.hi()
和t2.hello()
。他们可以同时执行还是有任何问题?
答案 0 :(得分:5)
否,同一对象中的2个同步方法不能同时执行:
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
从文档中
在同一对象上两次同步方法的调用是不可能交织的。当一个线程正在执行对象的同步方法时,所有其他为同一对象块调用同步方法的线程(挂起执行),直到第一个线程对该对象完成为止。
此处的键锁定在对象上。正如Thomas所指出的,大概t1
和t2
是同一类的不同实例,因此它们实际上可以同时执行hi()
和hello()
。
如果t1
和t2
是同一对象上调用hi()
和hello()
的两个不同线程,则上述语义成立,并且这两个方法无法在平行。
答案 1 :(得分:1)
在方法声明中使用synced关键字使用隐式 如果是静态方法,则该对象是类对象 非静态方法的情况下,实例对象本身。
示例1:
public class A {
public synchronized void setName() {
//
}
public synchronized void setAge() {
//
}
}
假设有两个线程Thread-1和Thread-2。
现在,线程1尝试访问setName()和线程2 setAge()
让线程1输入1st并按住密钥,线程2将等待直到密钥可用。困惑吗?
因此,由于没有显式对象用于同步,因此使用相同的键来同步这两种方法
“ A的对象,用于访问setName()方法和setAge() 分别由线程1和线程2来实现”。
A a = new A("Name", 1);
Runnable nameR = () -> a.getName();
Runnable ageR = () -> a.getAge();
Thread nameThread = new Thread(nameR);
Thread ageThread = new Thread(nameR);
nameThread.start();
ageThread.start();
但这是问题,因为即使具有键的线程无法访问其他线程,其他线程也无法运行其他方法。
因此,要解决此问题,我们需要分别使用单独的键来同步getName和getAge方法。
public class A {
private final Object nameLock = new Object();
private final Object ageLock = new Object();
public void setName() {
synchronized(nameLock) {
//
}
}
public synchronized void setAge() {
synchronized(ageLock) {
//
}
}
}
希望这会有所帮助!