每当我寻找并发访问时,我都会得到混合答案,我已经订购了JCIP书并且已经开始了,但是我想确定我的这个并发基础知识,这是我的方案
我有3个帖子。一个线程负责建立连接并创建一个单独的连接对象实例。另外两个线程将不断发送数据。
现在其他线程将在CountDownLatch
上等待,一旦建立连接,连接线程将把它倒计数到零。
以下是我在ConnectStatus
课程中声明的内容,希望connected
变量同步并且对所有主题都可见。
public class ConnectStatus {
public static final CountDownLatch connectionLatch = new CountDownLatch(1);
private static volatile AtomicBoolean connected;
}
我使用的是connected
变量,它是易变的&原子来维持连接状态。这样其他线程在发送数据之前就可以“始终”知道连接是否处于活动状态。
一旦建立连接,我将此布尔值设为true并将其锁定为零。
ConnectStatus.connected.set(true);
ConnectStatus.connectionLatch.countdown();
现在其他线程将被锁存器通知,并且原子值也将为true,并且线程开始发送数据。
在下面发送数据线索片段。
if(ConnectStatus.connected.get()){
// send data
}
现在这是我的问题,连接可能随时变坏并断开连接,所以那个时候,我将原子connected
视为假。我想知道的是,这个线程是否安全,我的其他线程是否总是得到这个原子,易变量的更新值?我需要另外两个线程在我的连接断开时停止发送数据。
if(ConnectStatus.connected.get()){
// send data
}
上述代码段是否始终正常运行?
答案 0 :(得分:3)
连接可能随时变坏并断开连接,所以那个时候,我将原子连接为假。我想知道的是,这个线程是否安全,我的其他线程是否总是得到这个原子,volatile变量的更新值?
是和否。首先,您的AtomicBoolean
应该是final
而不是 volatile
。 AtomicBoolean
包裹volatile boolean
,但您不会将其更改为其他AtomicBoolean
:
private static final AtomicBoolean connected = new AtomicBoolean(false);
仅使用AtomicBoolean
来保护连接的问题是(如@Jeff所提到的),即使您测试连接是否已连接,也可能会在之后直接断开连接。
if (ConnectStatus.connected.get()) {
// disconnect happens here, before the send
// send data
}
您无法使用AtomicBoolean
防止此断开连接。您需要有一个锁,以便断开连接的线程等待,直到所有发送完成:
private final Object lock = new Object();
...
synchronized (lock) {
if (connected) {
sendData();
}
}
...
// this has to wait for the lock to be released before it can be closed
synchronized (lock) {
if (connected) {
disconnect();
connected = false;
}
}
如果在连接断开时无法控制,则必须正确捕获异常并正确处理它们。
最后,如果您需要多个发件人,那么您应该查看ReentrantReadWriteLock
并让您的发件人锁定为“读者”(有趣),一次允许多个读者,并将结束线程锁定为“作家”,一次只允许一位作家。
答案 1 :(得分:2)
volatile
确保可见性,因此如果connected
变量由一个线程更新,则它将从另一个线程可见。但是,正如@Gray在他的评论中指出的那样,这并不是你正在做的事情。如果您没有进行原子比较和设置操作,则无需使用AtomicBoolean
。如果您只是阅读或撰写boolean
,那就是原子http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html。但是,你仍然有竞争条件。如果您检查get
connected
状态后,连接会断开怎么办?