简体   繁体   English

从同步块中调用此同步方法可以吗?

[英]Is it fine to call this synchronized method from a synchronized block?

Simply put, I'm wondering if this changes the behavior. 简而言之,我想知道这是否会改变行为。 I'm assuming yes, because calling someMethod() will lock the entire object, instead of just the list object? 我假设是的,因为调用someMethod()将锁定整个对象,而不只是列表对象? But I'm still new to this synchronization stuff, so I'd like some more educated feedback. 但是,我对这种同步工具仍然不熟悉,因此我需要一些受过良好教育的反馈。

The before: 之前:

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();
    }
}

You are correct - the new code has got different semantics, as someMethod() is indeed synchronized on the instance it is being invoked on (and as such, that synchronization is entirely unrelated to the one on list ). 您是正确的-新代码具有不同的语义,因为someMethod()确实在调用它的实例上同步(因此,同步与list那个完全无关)。 However, the call to someMethod() will take place while the monitor on list is being held, so a call to run() is "equally thread safe" with respect to list . 但是,对someMethod()的调用将在保持list的监视器的同时进行,因此,对run()的调用对于list而言是“平等线程安全的”。

On the other hand, you have now introduced the possibility for multiple threads to call someMethod() directly at the same time. 另一方面,您现在介绍了多个线程直接直接调用someMethod()的可能性。 You have also introduced a (probably unnecessary) potential for deadlock with other threads due to the extra synchronization on the object itself. 由于对象本身的额外同步,您还引入了(可能不必要)与其他线程发生死锁的可能性。 I would recommend this instead: 我建议改为:

public void someMethod() {
    synchronized (list) {
        try {
            list.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

This method is now safe both for individual use and for being called through run() - note that it is safe to synchronize on an object that you have already synchronized on; 现在,此方法对于个人使用和通过run()调用都是安全的-请注意,在已经同步的对象上同步是安全的; the thread won't block itself. 线程不会自身阻塞。

With syncronized you don't really 'lock' an object. 通过syncronized您实际上并不会“锁定”对象。 You will just make sure that access from everyone who is synchronizing on that specific object is 'regulated' with a lock. 您只需确保使用锁“限制”了正在对该特定对象进行同步的每个人的访问权限。

A synchronized method is synchronizing on this . 一个同步方法被同步于this

That means, if you enter a syncronized block on some object list you can call a syncronized method without a problem at first 这意味着,如果您在某个对象list上输入了syncronized块,则可以首先调用syncronized方法而不会出现问题。


Some things to be thought about: 需要考虑的一些事情:

This code doesn't produce a deadlock: 这段代码不会产生死锁:

public void foo() {
    synchronized (this) {
        someMethod();
    }
}

public synchronized void someMethod() {
    // ...
}

because you already have the "lock" on this , but this: 因为您已经this具有“锁定”,但这是:

public void foo() {
    synchronized (list) {
        someMethod();
    }
}

public synchronized void someMethod() {
    // ...
}

may produce a deadlock with some other thread! 可能与其他线程产生死锁! You'll have to be really careful if you enter a synchronized section within another synchronized section 如果您在另一个synchronized部分中输入一个synchronized部分,则必须非常小心

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM