[英]How to guarantee that all non-thread-safe references to an object will be synchronized?
Suppose I have a class: 假设我有一堂课:
public final class Server {
private final ArrayList<ServerConnection> connections;
private ServerConnection pending;
private Thread connector;
public Server() {
connections = new ArrayList<>();
connector = new Thread(() -> {
while (true) {
pending = new ServerConnection();
pending.waitForConnection();
//Could be adding while another thread is iterating.
connections.add(pending);
}
}, "Connection Establisher");
connector.setDaemon(true);
connector.setPriority(Thread.MIN_PRIORITY);
connector.start();
}
//Anyone with a refrence to this object can access connections.
public ArrayList<ServerConnection> getConnections() {
return connections;
}
}
How would I make sure that connections
is not in use while I add an object. 添加对象时,如何确保未使用
connections
。 I thought about using a synchronized (connections) {...}
block in the thread but from my knowledge of synchronized
blocks all non-thread-safe references to connections
would have to be in a synchronized block. 我曾考虑过在线程中使用
synchronized (connections) {...}
块,但是根据我对synchronized
块的了解,所有对connections
非线程安全引用都必须位于同步块中。 Is there some way that I can make sure that all non-thread-safe access to connections
are synchronized? 有什么方法可以确保所有对
connections
非线程安全访问都已同步?
Making the getConnections
method synchronized is not enough because once the caller gets a reference to the list, it can do whatever it wants with it, including thread unsafe operations. 使
getConnections
方法同步是不够的,因为一旦调用者获得对该列表的引用,它就可以用它做任何想要的事情,包括线程不安全的操作。
A few simple steps would make your code more robust: 一些简单的步骤将使您的代码更健壮:
A simple rewrite could look like the code below (it can certainly be improved) - check the comments. 一个简单的重写可能看起来像下面的代码(可以肯定会得到改善)-检查注释。 Note that it would work better if the
waitForConnection
reacted to interruption appropriately too, for example by throwing an InterruptedException
. 请注意,如果
waitForConnection
对中断做出适当的反应(例如,抛出InterruptedException
,则效果会更好。
public final class Server {
//us a thread safe list
private final List<ServerConnection> connections = new CopyOnWriteArrayList<>();
//make the thread final
private final Thread connector;
public Server() {
connector = new Thread(() -> {
//provide a mechanism to stop the thread: exit on interruption
while (!Thread.currentThread().isInterrupted()) {
ServerConnection pending = new ServerConnection();
pending.waitForConnection();
//Could be adding while another thread is iterating.
connections.add(pending);
}
}, "Connection Established");
//Note that the priority may be ignored at runtime
connector.setPriority(Thread.MIN_PRIORITY);
}
public void start() {
connector.start();
}
//to stop the thread, interrupt it
public void stop() {
if (!connector.isAlive()) throw new IllegalStateException("The server is not started");
connector.interrupt();
}
//don't return the list but an unmodifiable view of the list
public List<ServerConnection> getConnections() {
return Collections.unmodifiableList(connections);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.