简单地说,我想知道这是否会改变行为。我假设是,因为调用someMethod()会锁定整个对象,而不仅仅是列表对象?但我对这种同步的东西还是新手,所以我想要一些更有教育意义的反馈。
之前:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The After:
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();
}
}
答案 0 :(得分:2)
你是对的 - 新代码有不同的语义,因为someMethod()
确实在它被调用的实例上同步(因此,同步与{{1}上的同步完全无关})。但是,当list
上的监视器被保留时,someMethod()
的呼叫将被发生,因此list
的呼叫与run()
“同样是线程安全的”。
另一方面,您现在已经介绍了多个线程可以同时直接调用list
的可能性。由于对象本身的额外同步,您还引入了(可能不必要的)与其他线程死锁的可能性。我建议改为:
someMethod()
此方法现在对于个人使用和通过public void someMethod() {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
进行调用都是安全的 - 请注意,对已经同步的对象进行同步是安全的;线程不会阻塞自己。
答案 1 :(得分:2)
syncronized
你真的没有锁定'一个东西。您只需确保对该特定对象上同步的所有人的访问权限受到监管'带锁。
同步方法正在this
上进行同步。
这意味着,如果您在某个对象syncronized
上输入list
块,则可以先调用syncronized
方法而不会出现问题
有些事情要考虑:
此代码不会产生死锁:
public void foo() {
synchronized (this) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
因为你已经拥有"锁定"在this
,但是这个:
public void foo() {
synchronized (list) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
可能会与其他一些线程产生死锁!如果您在另一个synchronized
部分中输入synchronized
部分,则必须非常小心