java - 如何跨类使用同步块(synchronized block)?

标签 java multithreading synchronization

我想知道如何跨类使用同步块(synchronized block)。我的意思是,我想在多个类中使用同步块(synchronized block),但它们都在同一个对象上同步。我想到如何做到这一点的唯一方法是这样的:

//class 1
public static Object obj = new Object();

someMethod(){
     synchronized(obj){
         //code
     }
}


//class 2
someMethod(){
     synchronized(firstClass.obj){
         //code
     }
}

在此示例中,我创建了一个任意对象以在第一个类中进行同步,并且在第二个类中也通过静态引用对其进行同步。但是,这对我来说似乎是糟糕的编码。 有没有更好的方法来实现这一点?

最佳答案

拥有一个用作锁的静态对象通常是不可取的,因为在整个应用程序中一次只有一个线程可以取得进展。当您有多个类都共享同一个锁时,情况更糟,您最终可能会得到一个几乎没有实际并发性的程序。

Java 对每个对象都有内在锁的原因是对象可以使用同步来保护自己的数据。线程在对象上调用方法,如果需要保护对象免受并发更改,则可以将同步关键字添加到对象的方法中,以便每个调用线程必须先获取该对象的锁,然后才能在该对象上执行方法。这样,对不相关对象的调用就不需要相同的锁,并且您更有可能让代码实际并发运行。

锁定不一定是您的并发首选技术。实际上,您可以使用多种技术。按偏好降序排列:

1) 尽可能消除可变状态;不可变对象(immutable对象)和无状态函数是理想的,因为没有状态需要保护,也不需要锁定。

2) 尽可能使用线程限制;如果您可以将状态限制为单个线程,那么您可以避免数据竞争和内存可见性问题,并最大限度地减少锁定量。

3) 优先使用并发库和框架,而不是通过锁定滚动您自己的对象。熟悉 java.util.concurrent 中的类。这些比应用程序开发人员可以设法组合在一起的任何东西都要好得多。

在完成上面的 1、2 和 3 的尽可能多的操作后,您可以考虑使用锁定(其中锁定包括 ReentrantLock 等选项以及内部锁定)。将锁与 protected 对象相关联可以最大限度地减少锁的范围,这样线程就不会持有锁超过它需要的时间。

此外,如果锁不在被锁定的数据上,那么如果在某个时候您决定使用不同的锁而不是让所有东西都锁定在同一事物上,那么避免死锁可能具有挑战性。锁定需要保护的数据结构使锁定行为更容易推理。

完全避免内在锁的建议可能是过早的优化。首先确保您只锁定正确的东西。

关于java - 如何跨类使用同步块(synchronized block)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24771072/

相关文章:

java - 使用 mockito 模拟嵌套方法调用

java - 多线程旧版Java应用程序的线程按顺序轮流

c++ - 如何使用 OpenGL 在 Windows 上的同一个应用程序中绘制两个单独的 3D 窗口?

node.js - 在 Node js 中,libuv 是什么?它是否使用所有核心?

algorithm - 是否有任何同步算法/引用可用于同步目录?

java - 在PC上序列化,在android手机上反序列化?

java - 如何拥有必须至少运行一次的 public void 方法

Java 线程 NullPointerException

java - 为什么SynchronizedList的listIterator需要用户外部同步?

java - 为什么 "synchronized"对多态没有作用