Java线程无法读取主线程修改的数据?技术求助
问题原因:线程可见性缺失
你遇到的是Java多线程中的变量可见性问题。Java内存模型(JMM)规定,每个线程拥有独立的工作内存,线程对变量的读写操作默认只在自己的工作内存中进行,不会立即同步到主内存。
主线程修改notif[0].found和notif[0].reply后,这些修改可能仅停留在主线程的工作内存中,没有同步到主内存;而tS线程一直在读取自己工作内存中缓存的旧值(found=0),因此永远触发不了if(notif[0].found !=0)的逻辑。
解决方案
方案1:用volatile关键字修饰属性
volatile关键字能强制线程每次读取变量时直接从主内存获取,修改后立即写回主内存,确保变量修改对所有线程立即可见,同时禁止指令重排序。修改Notif类:
class Notif { public volatile int found; public volatile String reply; public Notif(int i){ found = i; } }
这个方案简单直接,适合你的场景——因为你只是对变量做简单的赋值和读取操作,没有复合的原子性需求。
方案2:用synchronized同步块/方法
synchronized不仅能保证线程互斥(同一时间只有一个线程执行同步代码),还能保证可见性:线程释放锁时会把工作内存的变量刷新到主内存,获取锁时会从主内存加载最新变量值。
修改主线程的修改逻辑:
synchronized (notif[0]) { notif[0].reply = "File " + msgs[i].fName + " found in " + msgs[i].Cx + ". - Computer " + nums.get(i); notif[0].found = 1; }
修改tS线程的读取逻辑:
while(System.currentTimeMillis() - start < hopCt*2000) { synchronized (notif[0]) { if(notif[0].found != 0){ System.out.println("found n"); replies.add(notif[0].reply); notif[0].found = 0; } } }
注意:同步块的锁对象必须是同一个(这里用notif[0]),否则无法保证可见性。
方案3:使用原子类(可选)
如果后续需要对found做复合操作(比如found++),可以用java.util.concurrent.atomic.AtomicInteger代替int,它内置了可见性和原子性保障:
class Notif { public AtomicInteger found = new AtomicInteger(0); public volatile String reply; public Notif(int i){ found.set(i); } }
主线程修改:
notif[0].found.set(1);
tS线程判断:
if(notif[0].found.get() != 0) { // ... notif[0].found.set(0); }
内容的提问来源于stack exchange,提问作者thesaferose_
相关产品推荐
相关产品推荐

