多线程应用程序中的原子布尔值用法
Atomic Boolean usage in multithreaded application
我正在尝试 运行 以下代码:
在我的构造函数中,我初始化了我的原子布尔值:
Atomic Boolean isChannelActive = new AtomicBoolean(false);
在我的写入方法中,我检查了这个布尔值并等待:
public ChannelFuture write(ByteBuf msgBuf) {
if (!isChannelActive.get()) {
try {
wait();
} catch (InterruptedException ex) {
logger.Error("Waiting interrupted", ex);
}
}
但问题是这个原子布尔值可以在程序运行时从不同的线程设置:
if (!isChannelActive.get()) {
try{ --- Right on here and program made a context switch at this time.
wait()
所以在这种情况下,我的原子布尔值将为真,我错过了 notifyAll() 事件,并且由于上下文切换将永远等待。
我怎样才能避免这个问题?
我知道同步块可能是一个选项,但我正在为这种情况寻找更优雅的选项。
如果您正在调用 wait()
,那么您已经 在 一个 synchronized
块中。您的场景是一个假设场景,因为调用 wait()
和 notifyAll()
的两个线程必须获得相同的对象监视器。
因此,您声明的地方不可能存在上下文切换[1]。在这里使用 AtomicBoolean
也没有任何优势(至少根据您所展示的内容),一个简单的 volatile boolean
也可以。
[1] 并非不可能,您可以编写代码以便在同步块之外进行条件检查,但那将是故意编写损坏的并发代码。
您不应混合使用不同级别的同步机制。
wait/notify
- 这是一个您不再需要使用的陈旧系统。用 wait/notify
可以做的一切都可以用 synchronized
或 Lock
来完成。
synchronized
- 这允许您同步代码,以便需要独占访问的部分不会相互干扰。
Lock
s - 有各种不同类型的锁,通常可以处理您喜欢的几乎任何访问控制。
Blocking...
- 这是更现代的方法 - 它使用数据结构来确保安全访问,而不是将同步放在代码中。
还有更多的功能集,例如 Phaser
和 Semaphore
可用于实现一些更常见的机制。
您正试图同时使用 atomics
和 wait/notify
。这不会没有困难。
您可能只需要 Lock
.
Lock channelActive = new ReentrantLock();
public void test() {
channelActive.lock();
try {
// Do your exclusive stuff here.
} finally {
channelActive.unlock();
}
}
我正在尝试 运行 以下代码:
在我的构造函数中,我初始化了我的原子布尔值:
Atomic Boolean isChannelActive = new AtomicBoolean(false);
在我的写入方法中,我检查了这个布尔值并等待:
public ChannelFuture write(ByteBuf msgBuf) {
if (!isChannelActive.get()) {
try {
wait();
} catch (InterruptedException ex) {
logger.Error("Waiting interrupted", ex);
}
}
但问题是这个原子布尔值可以在程序运行时从不同的线程设置:
if (!isChannelActive.get()) {
try{ --- Right on here and program made a context switch at this time.
wait()
所以在这种情况下,我的原子布尔值将为真,我错过了 notifyAll() 事件,并且由于上下文切换将永远等待。
我怎样才能避免这个问题?
我知道同步块可能是一个选项,但我正在为这种情况寻找更优雅的选项。
如果您正在调用 wait()
,那么您已经 在 一个 synchronized
块中。您的场景是一个假设场景,因为调用 wait()
和 notifyAll()
的两个线程必须获得相同的对象监视器。
因此,您声明的地方不可能存在上下文切换[1]。在这里使用 AtomicBoolean
也没有任何优势(至少根据您所展示的内容),一个简单的 volatile boolean
也可以。
[1] 并非不可能,您可以编写代码以便在同步块之外进行条件检查,但那将是故意编写损坏的并发代码。
您不应混合使用不同级别的同步机制。
wait/notify
- 这是一个您不再需要使用的陈旧系统。用wait/notify
可以做的一切都可以用synchronized
或Lock
来完成。synchronized
- 这允许您同步代码,以便需要独占访问的部分不会相互干扰。Lock
s - 有各种不同类型的锁,通常可以处理您喜欢的几乎任何访问控制。Blocking...
- 这是更现代的方法 - 它使用数据结构来确保安全访问,而不是将同步放在代码中。还有更多的功能集,例如
Phaser
和Semaphore
可用于实现一些更常见的机制。
您正试图同时使用 atomics
和 wait/notify
。这不会没有困难。
您可能只需要 Lock
.
Lock channelActive = new ReentrantLock();
public void test() {
channelActive.lock();
try {
// Do your exclusive stuff here.
} finally {
channelActive.unlock();
}
}