简体   繁体   中英

Java Array Element Visibility Between Several Threads

Creating the Array:

Uses the thread provided on startup since we only create the array once.

public static final Player[] PLAYERS = new Player[10];

Writing to Array:

Uses several different threads from a pool so that players can load concurrently.

public static Player loadPlayer(int freeIndex) {
    //slow code that loads the player's saved data.
    return PLAYERS[freeIndex] = player;
}

Reading from Array:

Uses a single thread to process players in order of their index.

public static void process() {
    for(Player player : PLAYERS)
        player.process();
}

Questions: Will players be immediately visible in method process after method loadPlayer is executed? If not (which I'm suspecting is the case) what approach should I take to fix the problem?

You are correct that the players may not be immediately visible.

You can use an AtomicReferenceArray instead of a standard array to ensure changes to players are visible to other threads.

From the documentation ,

The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in The Java Language Specification (17.4 Memory Model):

get has the memory effects of reading a volatile variable.

set has the memory effects of writing (assigning) a volatile variable.

lazySet has the memory effects of writing (assigning) a volatile variable except that it permits reorderings with subsequent (but not previous) memory actions that do not themselves impose reordering constraints with ordinary non-volatile writes. Among other usage contexts, lazySet may apply when nulling out, for the sake of garbage collection, a reference that is never accessed again.

weakCompareAndSet atomically reads and conditionally writes a variable but does not create any happens-before orderings, so provides no guarantees with respect to previous or subsequent reads and writes of any variables other than the target of the weakCompareAndSet. compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.

No, the value you set in one thread may not be available for another thread without synchronization. You can check here for more details about memory barrier.

In this case, you can use a CountDownLatch for synchronization.

  • In initiation, create a CountDownLatch :

     public static final Player[] PLAYERS = new Player[10]; public static CountDownLatch lacth = new CountDownLatch(10); 
  • After load a new Player , call countDown

     public static Player loadPlayer(int freeIndex) { //slow code that loads the player's saved data. PLAYERS[freeIndex] = player; latch.countDown(); return player; } 
  • In the process thread, just wait. After loading all Player , this thread will be called up by the last countDown thread:

     public static void process() { latch.await(); for(Player player : PLAYERS) player.process(); } 

When you are loading player using different thread ,modifying shared collection.When a concurrent program is not correctly written, the errors tend to fall into one of the three categories: atomicity, visibility, or ordering.

To make your code thread safe you need to use lock or some other nonblocking collection like AtomicReferenceArray which will ensure thread visibility and thread safe.Also volatile variable is not ensure atomicity but variable will ensure visibility .

Atomicity deals with which actions and sets of actions have indivisible effects. This is the aspect of concurrency most familiar to programmers: it is usually thought of in terms of mutual exclusion. Visibility determines when the effects of one thread can be seen by another. Ordering determines when actions in one thread can be seen to occur out of order with respect to another

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM