同步函数,还是锁定线程中的对象? [复制]

Posted

技术标签:

【中文标题】同步函数,还是锁定线程中的对象? [复制]【英文标题】:synchronize functions, or lock object in thread? [duplicate] 【发布时间】:2018-01-21 18:28:19 【问题描述】:

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

    class DBresource 

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

class MyThread extends Thread 

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

什么是可取的,为什么?

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

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

谢谢。

【问题讨论】:

@Makoto:我不同意,我认为这是关于锁定代码所属的位置,在受保护的资源中或在访问资源的任务中。 【参考方案1】:

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

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

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

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

【讨论】:

同意。并接受为答案。谢谢。你能扩展类级别的锁吗?如果一个线程在一个对象上获得了锁,那么只有在同一个对象上等待锁的线程才会等待。同样,如果一个线程在类本身上获得了锁,那么只有想要在这个类上获得锁的线程才会等待。不?如果是,类级锁比对象级锁差多少? @jforex78 是的,是的,更糟糕​​的是,如果你用一个类级锁代替一个实例级锁,你会锁定所有线程,但所有实例的所有方法中的一个,甚至如果他们只使用一个实例而不使用静态变量。【参考方案2】:

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

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

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

【讨论】:

以上是关于同步函数,还是锁定线程中的对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

python lock, semaphore, event实现线程同步

适当使用同步或锁定一段代码

Java线程同步块行为 - 同步与同步()? [复制]

同步使对象锁定

Java多线程---同步与锁

多线程