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

时间:2017-08-13 23:14:02

标签: java multithreading synchronization synchronized

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

    class DBresource {

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

OR

class MyThread extends Thread {

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

哪个是可取的,为什么?

此外,我也可以锁定类DBResource。那有什么不同?

或者,使用专用的Lock对象。是劝阻还是偏好?为什么?

感谢。

2 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:0)

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

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

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