是否需要将java servlet中的多个线程访问的变量声明为volatile?

MCS*_*MCS 1 java concurrency multithreading servlets

Java Servlet Programming一书中,第54页有一个示例servlet,它在后台线程中搜索素数.每次客户端访问servlet时,都会返回最近找到的素数.

用于存储最近找到的素数的变量声明为:

long lastprime = 0;
Run Code Online (Sandbox Code Playgroud)

由于这个变量是从多个线程(正在进行计算的后台线程和正在访问它的任何客户端线程)开始访问的,所以它不需要声明为volatile还是以某种方式使其访问同步?

Jon*_*eet 8

是的,假设你真的想在任何线程上看到最近计算的素数,它应该是易失性的,或者通过synchronized块/方法以线程安全的方式访问.另外,正如注释中所指出的,非易失性长变量可能无法原子更新 - 因此您可以看到旧值的前32位和新值的后32位(反之亦然).

我之前忘记了原子性方面,因为当你确保获得最近发布的值时,它几乎总是自动解决,并确保你完全发布新值.在实践中,这几乎总是你想要的,所以如果你的代码正常工作,原子性就不会成为问题.

它不是SingleThreadModelservlet吗?那显然会产生影响.

另一种选择是使用AtomicLong.

  • 它不只是看到最近的价值,它是(a)看到任何公布的价值 - 不能保证你不会在读者线程中永远看到'0',更重要的是(b)看到正确的价值.非易失性longs的更新不是原子的,您可能会看到旧值的底部32个字节和新值的前32个(反之亦然) - 这可能根本不是素数! (3认同)