Java 如何保证对对象的所有非线程安全引用都将同步?
假设我有一门课:Java 如何保证对对象的所有非线程安全引用都将同步?,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,假设我有一门课: public final class Server { private final ArrayList<ServerConnection> connections; private ServerConnection pending; private Thread connector; public Server() { connections = new ArrayList<>(); connector = new Thread((
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;
}
}
公共最终类服务器{
私有最终ArrayList连接;
私有服务器连接挂起;
专用螺纹连接器;
公共服务器(){
连接=新的ArrayList();
连接器=新螺纹(()->{
while(true){
挂起=新服务器连接();
挂起。waitForConnection();
//可以在另一个线程迭代时添加。
连接。添加(待定);
}
}“连接建立者”);
connector.setDaemon(true);
连接器设置优先级(线程最小优先级);
connector.start();
}
//任何引用此对象的人都可以访问连接。
公共ArrayList getConnections(){
返回连接;
}
}
如何确保添加对象时,
连接
未被使用。我曾考虑在线程中使用synchronized(connections){…}
块,但根据我对synchronized
块的了解,对连接的所有非线程安全引用都必须在同步块中。是否有某种方法可以确保对连接的所有非线程安全访问都是同步的?使getConnections
方法同步是不够的,因为一旦调用方获得对列表的引用,它就可以对它做任何它想做的事情,包括线程不安全的操作
以下几个简单步骤将使您的代码更加健壮:
- 仅使用最终变量
- 提供启动和停止方法。此时,您在构造函数中启动线程并泄漏对此的引用—这可能会产生奇怪的可见性效果。您不需要管理线程停止,而是让线程成为守护进程—它可以工作,但可能没有那么干净
一个简单的重写可能看起来像下面的代码(当然可以改进)-检查注释。请注意,如果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);
}
}
公共最终类服务器{
//给我们一个线程安全列表
私有最终列表连接=新建CopyOnWriteArrayList();
//使线程最终
专用终螺纹接头;
公共服务器(){
连接器=新螺纹(()->{
//提供停止线程的机制:中断时退出
而(!Thread.currentThread().isInterrupted()){
ServerConnection pending=新建ServerConnection();
挂起。waitForConnection();
//可以在另一个线程迭代时添加。
连接。添加(待定);
}
}“建立联系”);
//请注意,在运行时可能会忽略优先级
连接器设置优先级(线程最小优先级);
}
公开作废开始(){
connector.start();
}
//要停止线程,请中断它
公共停车场(){
如果(!connector.isAlive())抛出新的非法状态异常(“服务器未启动”);
connector.interrupt();
}
//不返回列表,而是返回不可修改的列表视图
公共列表getConnections(){
返回集合。不可修改列表(连接);
}
}