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();
}
}
如何在调用另一个方法之前锁定一个方法?
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();
}
}