同步函数,或锁定线程中的对象?

synchronize functions, or lock object in thread?

我们可以同步一个class中的函数,或者我们可以在线程中锁定它的对象,以在对象上创建线程安全。

    class DBresource {

        synchronized public void dosomething() throws InterruptedException {
            ...
            ...
        }
    }

class MyThread extends Thread {

    public void run() {
        synchronized (r) {
            r.dosomething();
        }
}

哪个是可取的,为什么?

此外,我还可以锁定 class DBResource。那会有什么不同?

或者,使用专用的 Lock 对象。这是不鼓励还是更喜欢,为什么?

谢谢。

如果您使用第二种方法,将锁定逻辑放在线程中,那么每次您需要不同的任务来访问该资源时,您都必须向新任务添加锁定代码。如果接触该资源的任何任务不执行锁定或搞乱了它们的执行方式,那么该资源可能会损坏。这将导致一个脆弱的应用程序,如果添加代码的人没有完全正确地锁定,添加功能可能会导致破坏。它也是 DRY 的对立面。

对于第一种方法,对象通过实施访问它所需的任何锁定来保护自己。任何访问该对象的线程都必须获得 class 指定的锁。任何线程都没有机会绕过对资源的锁定。

使用专用锁,例如使用私有最终实例成员,可以使不相关的代码更难获得对象上的锁。恶意代码仍然可以使用反射,但它可以防止意外访问。

使用class级锁可以防止多个线程访问资源,即使有多个资源也是如此。你可以用这种方式制造瓶颈。

制作方法 synchronized 是最简单的,并且不会对调用者强加任何要求,除了他们以通常的方式避免死锁。

然而,它并未涵盖所有情况。例如,如果你正在迭代一个集合,你应该在一个同步集合的块内进行,以防止它在你的迭代期间被修改(除非你使用并发安全的集合,当然像java.util.concurrent)。通常,如果您以需要在所有调用中保持一致状态的方式调用一个对象的多个方法,则需要在外部对其进行同步。

所以关于哪个更好的问题并没有真正的答案。这取决于你在做什么。