看看网络上的其他示例,当通过 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) {
...
最佳答案
您需要使用volatile
关键字,如果某个变量被某个线程修改,但可能被另一个线程读取(并且没有任何其他同步机制)。
所以问题是是否存在某些线程更改Set
的场景到另一个线程,第二个线程尝试访问它。例如,如果某个线程执行此操作:endPoint = new HashSet<>()
,而另一个线程执行此操作:endPoint.get(...)
,那么是的,Set
应该是volatile
。
但是如果不同的线程使用相同的Set
实例,然后 endPoint
引用不会改变,并且是“有效的最终”。在这种情况下,无需添加 volatile
关键字。
所以简短的答案是“这取决于”,因为我们需要查看完整的示例来看看 Set
是否有效。应该是不稳定的。不过,我确实想指出一件事 - 使用 CopyOnWriteArraySet
似乎有点奇怪,因为对集合的修改只会在修改线程的上下文中创建修改后的副本(这就是写时复制的含义)。
关于java - Server EndPoint for WebSocket Java API 中的 volatile 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48099722/