Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何保证对对象的所有非线程安全引用都将同步?_Java_Multithreading_Synchronization_Thread Safety - Fatal编程技术网

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(){
返回集合。不可修改列表(连接);
}
}