从同步块调用此同步方法是否可以?

时间:2016-07-24 21:33:20

标签: java multithreading asynchronous

简单地说,我想知道这是否会改变行为。我假设是,因为调用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();
    }
}

2 个答案:

答案 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部分,则必须非常小心