Server EndPoint for WebSocket Java API中的易变变量?

问题描述 投票:1回答:1

查看Web上的其他示例,当通过Java API for WebSocket创建服务器端点时,所有EndPoint实例之间的共享变量被定义为静态,但不是volatile。我想知道原因。

据我所知,打开websockets的客户端将在服务器中创建一个新线程。那么要是线程安全的,不应该在EndPoint实例之间定义为volatile的共享变量吗?

即代替:

@ServerEndpoint("/endpoint")
public class WebsocketEndPoint {
   private static Set<WebsocketEndPoint> endPoint = new CopyOnWriteArraySet<WebsocketEndPoint> ();

   @OnOpen
   public void onOpen(Session session, String message) {
...

这段代码不是更好吗?:

@ServerEndpoint("/endpoint")
public class WebsocketEndPoint {
   private static volatile Set<WebsocketEndPoint> endPoint = new CopyOnWriteArraySet<WebsocketEndPoint> ();

   @OnOpen
   public void onOpen(Session session, String message) {
...
java multithreading websocket thread-safety volatile
1个回答
0
投票

您需要在某些线程修改变量的情况下使用volatile关键字,但可以由不同的线程读取(并且没有任何其他同步机制)。

所以问题是是否存在某个线程将Set更改为其他线程并且第二个线程尝试访问它的场景。例如,如果某个线程执行此操作:endPoint = new HashSet<>(),而另一个线程执行此操作:endPoint.get(...),然后是,Set应该是volatile

但是,如果不同的线程使用相同的Set实例,那么endPoint引用不会改变,并且是“有效的最终”。在这种情况下,不需要添加volatile关键字。

所以简短的回答是“它取决于”,因为我们需要查看完整的例子,看看Set是否应该是易变的。我确实想要指出一件事 - 使用CopyOnWriteArraySet似乎有点奇怪,因为对集合的修改只会在修改线程的上下文中创建一个修改后的副本(这就是copy-on-write的意思)。

© www.soinside.com 2019 - 2024. All rights reserved.