You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 09:42:38