Java: volatile enough to make classes threadsafe?

杀马特。学长 韩版系。学妹 提交于 2019-12-03 18:04:21

Reads and writes of references are always atomic in Java, so there is no danger of, for example, seeing the reference in some half-updated state. If this is what you mean by "thread safe" then the operation is thread safe with or without the keyword.

But volatile is not about atomicity, it affects whether threads can cache writes locally. volatile would force writes to be written back to main memory and be visible to other threads. If that is what you mean by thread-safe, then yes you need this keyword.

volatile itself does not affect whether method calls on foo exclude other threads or not. If that's what you mean you want to use synchronized, and in a different place.

volatile ensures that a thread reading the variable will see the new value set in this variable before by another thread. It won't see a stale value stored in a processor cache.

Whether it makes the whole program thread-safe depends on what the program does, how it uses the variable, and how the Foo class is designed.

volatile is not enough.

I believe this example demonstrates one situation where volatile is not enough:

Shared object:

public class Blammo
{
  public String kapow;
}

Code in thread 1:

Blammo blammo = new Blammo();
blammo.kapow = "zowie";
if ((blammo.kapow != null) && (blammo.kapow.isEmpty()))
{
  ...
}

Code in thread 2:

blammo.kapow = null;

Thread 1 is executing and executes (blammo.kapow != null).
Thread 1 swaps out and Thread 2 swaps in.
Thread 2 executes (blammo.kapow = null).
Thread 2 swaps out and Thread 1 swaps in.
Thread 1 now executes (blammo.kapow.isEmpty()) and throws a null pointer exception.

If the only thing you do is setting this variable, than yes, volatile is enough. As pointed out in the comments, you need volatile to make the changes visible (however, you will not have any corrupt updates without volatile, like you could have with long or double, see below).

By default, reading and writing of reference variables (references to objects) are atomic, as are reading and writing to most primitive types (except for long and double).

With volatile you can make sure that reads and writes to variables of type long and double are also atomic, which you don't need in this case.

So, yes, in this example, it is enough. However, if you're planning on sending more complex messages, consider using tools from java.util.concurrent.*

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!