什么是类级别,对象级别,显式和内部锁定?

我一直在经历Javamultithreading概念。 我经历的越多,我就越困惑。

现在我不理解Java中的类级别,对象级别,显式锁定和内部锁定之间的差异。 有人可以让我知道这是什么? 另外,如果我能得到一些例子来理解,那对我来说非常有帮助。

显性vs内在

当您在对象上使用synchronized或间接作为方法签名的一部分时,您将创建一个内部锁 。 您依赖与所有对象和类关联的内置锁。

java.util.concurrent.locksjava.util.concurrent.locks Java 5+中提供了显式锁。 最常用的类可能是ReentrantLock 。 这些提供了使用内在锁的替代方案,并提供了内部锁无法实现的function。

类级别与对象级别

这种区别仅适用于内在锁。 如果您有一个同步静态方法 ,则使用的内部锁定将与类对象本身相关联。 如果在对象实例上进行同步(或具有同步的实例方法),则它将是对象级锁定。

进一步阅读

Brian Goetz的Java Concurrency in Practice是一本很好的书,用于理解Java中multithreading编程的混乱世界。

使用“已同步 ”关键字时,它使用内部锁或监视器。 Java中的每个对象都有一个与之关联的内部锁。 每当线程尝试访问同步块或方法时 ,它就会获取该对象或对象级别锁定内部锁或监视器 。 在静态方法的情况下,线程获取对类对象锁定

 public synchronized void doAtomicTransfer(){ //enter synchronized block , acquire lock over this object. operation1() operation2(); } // exiting synchronized block, release lock over this object. 

内在锁定机制可能具有一些function限制,例如:

  • 无法中断等待获取锁定的线程(可中断锁定)。
  • 在不愿意永远等待它的情况下尝试获取锁是不可能的(尝试锁定)。 只有一个线程可以同时保持锁定:例如,没有任何设施允许多个线程同时持有锁以进行只读访问。
  • 无法实现非块结构锁定规则,因为必须在获取它们的同一块中释放内部锁。

在需要克服内置同步的一些缺点的情况下, 显式锁非常有用。 特别是,它们具有以下特征:

  • 线程可以尝试中断获取锁定;
  • 线程可以为尝试获取锁定提供超时值;
  • 支持读/写锁 – 即,如果没有锁定写入锁,则允许多个并发读取器的锁;
  • 传统的等待/通知隐喻被扩展为允许条件(见下文);
  • 支持公平性(如果多个线程正在等待锁定,它们在可用时以先进先出顺序获取);
  • 锁定超出块范围的能力:例如,一个方法可以将锁定对象传递给另一个线程;
  • 可以查询锁定以查找,例如,它们是否有任何线程等待获取它们。

“类级”锁定和“对象级”锁定是由作者创建的,这些作者可能对Java的内部锁定工作原理没有深入的理解。

类级锁定如下所示:

 class Foobar { static synchronized void moo() { ... } } 

但这种结构实际上只是一种简写的写作方式:

 class Foobar { static void moo() { synchronized (Foobar.class) { ... } } } 

和对象级锁定,如下所示:

 class Foobar { synchronized void baa() { ... } } 

只是简写:

 class Foobar { static void baa() { synchronized (this) { ... } } } 

实际上,在“类级”和“对象级”锁定之下,只有一个概念,即synchronized块:

 synchronized(objectReference) {...} 

您需要知道的是,JVM不允许多个线程同时在同一个对象上同步。

当您要保护的数据是全局数据时,在访问数据时同步全局单例对象是有意义的。 Foobar.class是一个全球性的单身人士。

当您要保护的数据完全包含在某个对象实例中时,那么在与该实例关联的内容上或在实例本身(即, this )上进行同步是有意义的。

当您想要同步非静态方法或非静态代码块时,对象级锁定是一种机制,这样只有一个线程能够在给定的类实例上执行代码块。 应始终这样做以使实例级数据线程安全。

 public class DemoClass { public synchronized void demoMethod(){} } or public class DemoClass { public void demoMethod(){ synchronized (this) { //other thread safe code } } } or public class DemoClass { private final Object lock = new Object(); public void demoMethod(){ synchronized (lock) { //other thread safe code } } } 

类级别锁定可防止多个线程在运行时的所有可用实例中的同步块中输入。 这意味着如果在运行时有100个DemoClass实例,那么一次只有一个线程可以在任何一个实例中执行demoMethod(),并且其他所有实例都将被锁定用于其他线程。 应始终这样做以使静态数据线程安全。

 public class DemoClass { public synchronized static void demoMethod(){} } or public class DemoClass { public void demoMethod(){ synchronized (DemoClass.class) { //other thread safe code } } } or public class DemoClass { private final static Object lock = new Object(); public void demoMethod(){ synchronized (lock) { //other thread safe code } } }