多线程Java数组元素在多个线程之间的可见性
创建数组:
Uses the thread provided on startup since we only create the array once.
public static final Player[] PLAYERS = new Player[10];
写入数组:
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;
}
从数组读取:
Uses a single thread to process players in order of their index.
public static void process() {
for(Player player : PLAYERS)
player.process();
}
问题:在方法loadPlayer执行后,玩家是否会立即在方法过程中可见?如果不是(我怀疑是这样),我应该采取什么方法来解决问题
# 1 楼答案
不,如果没有同步,在一个线程中设置的值可能无法用于另一个线程。您可以查看here以了解有关内存屏障的更多详细信息
在这种情况下,可以使用^{} 进行同步
在初始化中,创建一个
CountDownLatch
:加载新的
Player
后,调用countDown
在进程线程中,只需等待。在加载所有
Player
之后 线程将由最后一个countDown
线程调用:# 2 楼答案
你说得对,玩家可能不会立即出现
可以使用^{} 而不是标准数组,以确保对
players
的更改对其他线程可见从documentation
# 3 楼答案
当您使用不同的线程加载播放器时,请修改共享集合。当并发程序编写不正确时,错误往往会分为三类:原子性、可见性或顺序
为了使代码线程安全,需要使用lock或其他非阻塞集合,如AtomicReferenceArray,以确保线程可见性和线程安全。另外,volatile变量不能确保原子性,但变量将确保可见性
原子性涉及哪些动作和动作集具有不可分割的效果。这是程序员最熟悉的并发方面:它通常被认为是互斥的。可见性决定了一个线程的效果何时可以被另一个线程看到。排序决定了一个线程中的操作何时会相对于另一个线程出现无序