Java 从同步块调用此同步方法可以吗?
简单地说,我想知道这是否会改变行为。我假设是,因为调用someMethod()将锁定整个对象,而不仅仅是列表对象?但我对这种同步的东西还是比较陌生,所以我想得到一些更有教育意义的反馈 之前的:Java 从同步块调用此同步方法可以吗?,java,multithreading,asynchronous,Java,Multithreading,Asynchronous,简单地说,我想知道这是否会改变行为。我假设是,因为调用someMethod()将锁定整个对象,而不仅仅是列表对象?但我对这种同步的东西还是比较陌生,所以我想得到一些更有教育意义的反馈 之前的: public void run() { int i = 0; while (!end) { synchronized (list) { while (list.size() == i) { try {
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
之后:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
someMethod();
}
}
}
}
public synchronized void someMethod() {
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
您是正确的-新代码具有不同的语义,因为
someMethod()
确实在其被调用的实例上进行了同步(因此,该同步与列表上的同步完全无关)。但是,对someMethod()
的调用将在按住list
上的监视器时发生,因此对run()
的调用相对于list
而言是“同样线程安全的”
另一方面,您现在引入了多个线程同时直接调用someMethod()
的可能性。由于对象本身的额外同步,您还引入了(可能是不必要的)与其他线程发生死锁的可能性。我建议改为:
public void someMethod() {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此方法现在对于个人使用和通过run()
调用都是安全的-请注意,在已同步的对象上同步是安全的;线程不会阻塞自身。您是正确的-新代码具有不同的语义,因为someMethod()
确实在其被调用的实例上进行了同步(因此,该同步与列表上的同步完全无关)。但是,对someMethod()
的调用将在按住list
上的监视器时发生,因此对run()
的调用相对于list
而言是“同样线程安全的”
另一方面,您现在引入了多个线程同时直接调用someMethod()
的可能性。由于对象本身的额外同步,您还引入了(可能是不必要的)与其他线程发生死锁的可能性。我建议改为:
public void someMethod() {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此方法现在对于个人使用和通过run()
调用都是安全的-请注意,在已同步的对象上同步是安全的;线程不会阻塞自身。通过同步
不会真正“锁定”对象。您只需确保对该特定对象进行同步的每个人的访问都通过锁进行“管理”
已同步的方法正在上同步此
这意味着,如果您在某个对象的列表上输入syncronized
块
,您可以调用syncronized
方法,一开始不会出现问题
需要考虑的一些事情:
此代码不会产生死锁:
public void foo() {
synchronized (this) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
因为您已经在上锁定了此
,但是:
public void foo() {
synchronized (list) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
可能会与其他线程产生死锁!如果您在另一个synchronized
节中输入synchronized
节,您必须非常小心,因为synchronized
不会真正“锁定”对象。您只需确保对该特定对象进行同步的每个人的访问都通过锁进行“管理”
已同步的方法正在上同步此
这意味着,如果您在某个对象的列表上输入syncronized
块
,您可以调用syncronized
方法,一开始不会出现问题
需要考虑的一些事情:
此代码不会产生死锁:
public void foo() {
synchronized (this) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
因为您已经在上锁定了此
,但是:
public void foo() {
synchronized (list) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
可能会与其他线程产生死锁!如果在另一个synchronized
节中输入synchronized
节,您必须非常小心