Java 同步优于锁API的优点

Java 同步优于锁API的优点,java,multithreading,Java,Multithreading,我在每个博客或解释中都看到了锁API相对于同步的优势 我想知道同步比锁有什么优势,或者我更喜欢同步而不是锁的场景。你是说synchronized语句和方法关键字吗?隐式锁定的主要优点是需要更少的代码,并在离开其作用域时自动解锁。对于简单的锁定/等待操作,它是完美的解决方案 所以下面的代码 public void myMethod() { synchronized(this) { // concurrent stuff } } 完全等同于 final private

我在每个博客或解释中都看到了锁API相对于同步的优势


我想知道同步比锁有什么优势,或者我更喜欢同步而不是锁的场景。

你是说synchronized语句和方法关键字吗?隐式锁定的主要优点是需要更少的代码,并在离开其作用域时自动解锁。对于简单的锁定/等待操作,它是完美的解决方案

所以下面的代码

public void myMethod() {
    synchronized(this) {
       // concurrent stuff
    }
}
完全等同于

final private Lock lock = new ReentrantLock();

public void myMethod() {
    lock.lock();
    try {
        // concurrent stuff
    }
    finally {
        lock.unlock();
    }
}

您还可以使用不同的对象进行同步(它们不受任何影响,只是控制点):


除了@Shepard的答案外,使用
synchronized
更不容易出错。考虑这些错误会导致锁未被释放:

final private Lock lock = new ReentrantLock();

public void myMethod() {
    lock.lock();
    // concurrent stuff
}

public void myMethod2() {
    lock.lock();
    // concurrent stuff that might throw an unchecked exception
    lock.unlock();
}

public void myMethod3() {
    lock.lock();
    try {
       // concurrent stuff
       lock.unlock();
    } catch ( ... ) {
       ...
    } finally {
       ...
    }
}
第一种可能会出现在测试中,但后两种可能不会出现

使用
synchronized
,您不能犯任何这些错误


然而,
Lock
是有用的,尽管有以下注意事项:

  • 锁允许您实现不同的锁定策略,例如非重入锁定和多读/单写器锁定

  • 锁允许跨作用域/块结构边界持有锁。(这使您的代码更难推理,但对于某些用例来说是必要的;例如,基于事件的设计需要在多个事件处理程序之间保持锁。)

  • Lock API允许您测试锁,在不阻塞或超时的情况下获取锁,并定义
    条件
    对象

final static private Object sync = new Object();

public void method1() {
    synchronized(sync) {
        // concurrent code involving static members
    }
}

public void method2() {
     synchronized(this) {
         // concurrent code affecting this instance
     }
}
final private Lock lock = new ReentrantLock();

public void myMethod() {
    lock.lock();
    // concurrent stuff
}

public void myMethod2() {
    lock.lock();
    // concurrent stuff that might throw an unchecked exception
    lock.unlock();
}

public void myMethod3() {
    lock.lock();
    try {
       // concurrent stuff
       lock.unlock();
    } catch ( ... ) {
       ...
    } finally {
       ...
    }
}