Java 锁定方法

Java locking methods

如何在调用另一个方法之前锁定一个方法?

public class TestLock{
    public void methodIsLockedAfterFirstCall(){
        doSomething();
        //now lockThisMethod (when invoked, the thread shall sleep)
    }
     public void methodToDoSomethingAfterTheFirstMethod(){
         doSomeOtherThing()
         //unlock the first Method?
     }
}

Java 中是否已有相关内容,或者我应该以某种方式解决(例如 Boolean 或 AtomicLong)?

如果你想根据基本原则构建它,你可以这样做:

private final AtomicBoolean lock = new AtomicBoolean();

public void methodIsLockedAfterFirstCall() {
    doSomething();
    synchronized (lock) {
        while (lock.getAndSet(true)) try {
            lock.wait();
        } catch (InterruptedException e) {
            return; // SEE NOTE 1
        }
    }
}

public void methodToDoSomethingAfterTheFirstMethod() {
    doSomeOtherThing();
    synchronized (lock) {
        lock.set(false):
        lock.notifyAll();
    }
}

此代码:

  • 使用私人锁。仅当您记录此行为并为将来的版本维护此行为(或将您的新版本标记为与旧版本完全不兼容)时,锁定 om public 才是可接受的。通常,public 锁是错误的。因此,在 this 上同步通常是错误的。此代码锁定一个私有变量。

  • 此代码不 运行 使用 AtomicBoolean 的 JMM 问题。

  • 注意 1:InterruptedException 仅在 you(或 JVM 上的其他代码 运行ning)显式调用 .interrupt() 时发生在线程上(如果用户点击 CTRL+C,或 killall YourProcess,或任务管理器中的 'end task',或任何其他不涉及代码的方式,则不会发生 运行正在那个调用 .interrupt() 的 VM 中运行。怎么办?好吧, 而不是 只是 e.printStackTrace(),通常 java 不知道的程序员的中流砥柱他们在做什么。当你在代码库的其他地方写 thread.interrupt() 时,你想发生什么?做那个。如果 'stop waiting for that second call now' 的概念是一个明智的想法,那么在这个方法中记录行为. 这里我选择了 return (停止等待),但保持锁处于锁定状态。

  • 不使用notify/wait作为数据通信机制;仅作为一种沟通何时等待和何时停止等待的机制。这通常是个好主意,当 'were you notified or not' 捕获该状态时,很难调试相关状态,并且无法使用 wait(timeout) 变体。这就是为什么有一个 while 循环。被唤醒只会导致再次尝试 getAndSet,这可能会导致等待更多。这是好事。

或者,使用 j.u.concurrent 中的内容。一些想法:

  • 第一种方法锁定,第二种方法解锁的Lock
  • A Semaphore 听起来不对,因为 .release() 总是将计数加 1,因此如果您在 'lock status' 解锁时调用第二种方法,您会错误地添加许可证。你不能做 if (semaphore.availablePermits() < 1) semaphore.release(); 因为那会有竞争条件,除非你在 synchronized 块中这样做有点违背目的。

java.util.concurrent.locks and java.util.concurrent包下有很多

也许 CountDownLatch更容易使用的:

private final CountDownLatch latch = new CountDownLatch(1);

public class TestLock{
    public void methodIsLockedAfterFirstCall() throws InterruptedException {
        doSomething();
        //now lockThisMethod (when invoked, the thread shall sleep)
        latch.await()
    }
    public void methodToDoSomethingAfterTheFirstMethod(){
        doSomeOtherThing()
        //unlock the first Method?
        latch.countDown();
    }
}