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

时间:2014-10-31 13:03:22

标签: java multithreading locking

我一直在研究Java多线程概念。我经历的越多,我就越困惑。

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

4 个答案:

答案 0 :(得分:2)

显式vs内在

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

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

班级与对象级别

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


进一步阅读

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

答案 1 :(得分:1)

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

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

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

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

Explicit locks 非常有用。特别是,它们具有以下特征:

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

答案 2 :(得分:0)

"类级"锁定,"对象级"锁定是一种人为的想法,由作者创建,他们可能对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)上进行同步是有意义的。

答案 3 :(得分:-1)

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

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
        }
    }
}