The problem

Multiple threads read a HashMap at the same time, and one thread periodically retrieves the latest data, builds a new HashMap, and points the old reference to the new HashMap. This is a CopyOnWrite similar to the following code, which does not require real-time updates of the data (tolerating data that is not up to date), and all Is it safe for threads to tolerate not seeing each other’s latest data?

public class myClass {
    private HashMap<String,String> cache = null;
    public void init(a) {
        refreshCache();
    }
    // this method can be called occasionally to update the cache.
    public void refreshCache(a) {
        HashMap<String,String> newcache = new HashMap<String,String>();
        newcache.put("key"."value"); // code to fill up the new cache
        // and then finally
        cache = newcache; //assign the old cache to the new one in Atomic way}}Copy the code

answer

This is not safe, and a HashMap needs to be declared volatile to be safe

extension

There is a lot of evidence that volatile is volatile, and that individual threads can see the value of volatile variables in real time. This explanation is correct but incomplete, misleading to developers (including the problems encountered in this article), and does not go into the JVM’s happen before

The JVM optimizes the reordering of instructions, and although A is written before B, B may be executed before A. To avoid this problem, use happen-before

There are eight principles of happen before:

  • Single-thread happen-before principle: In the same thread, the previous actions happen-before the actions that follow.
  • Lock happens before: Unlock operation of the same lock happens before lock operation of the same lock.
  • The happen-before rule for volatile: Writes to a volatile variable happen-before any operations (including writes) to that variable.
  • The coincidentally -before transitivity principle: if A happens -before B, B happens -before C, then A happens -before C.
  • The happen-before rule for thread starts: start methods of the same thread happen-before other methods of this thread.
  • The coincidentally -before principle for thread interrupts: a call to the threadinterrupt method happens -before the code sent by the interrupted thread that detected the interrupt.
  • The happen-before principle of thread termination: All operations in a thread happen-before thread termination detection.
  • The happen-before principle for object creation: an object is initialized before its Finalize method is called.

A variable declared as volatile meets the happen-before principle. Writes to this variable always happen-before other operations, hence other articles explaining that volatile is visible to other threads. Visibility is the appearance, and happen-before is the cause

In this example, if volatile is not present and the cost-before rule is not met, the JVM will reorder the instructions. Cache = newcache may precede newcache.put(“key”, “Value “), if another thread reads the HashMap, it will not find the data, in other words, it is not thread safe to write this way.

lesson

For threading issues, you don’t know enough or understand enough, or you just stick with the implementation classes provided by the JDK, which have been honed a lot and are not as simple as they seem

The resources

  • Stackoverflow.com/questions/5…
  • Stackoverflow.com/questions/3…
  • www.cnblogs.com/m2492565210…