Java多线程,无事前发生关系
作者:互联网
我有两个使用相同对象obj的线程,并且由于读取了事前关系,因此我已经读过线程A在obj中所做的每个更改对于线程B都是可见的.
我想做的是相反的,在线程A中更改obj,而从线程B中看不到它,但是我不知道如何执行此操作.
我尝试在线程B中创建一个ThreadLocal,在run()方法中进行设置,并在线程B中使用ThreadLocal.get()而不是obj,但它一直在读取更改.
有谁知道如何实现这一目标?
提前致谢
编辑:(MVCE)
public class MyThreadLocal {
public static final ThreadLocal<Email> threadLocal = new ThreadLocal<Email>();
public static void set(Email email) {
threadLocal.set(email);
}
public static void remove() {
threadLocal.remove();
}
public static Email get() {
return threadLocal.get();
}
}
主线
serviceEnvioTaskSpring.setThreadName(getIdInstanciaOrigen()); //serviceEnvioTaskSpring is an instance of a class which implements Runnable
//set some more class' attributes
serviceEnvioTaskSpring.setEmail(email); //email is the shared object
ExecutorService threadExecutor = Executors.newCachedThreadPool();
threadExecutor.execute(serviceEnvioTaskSpring);
threadExecutor.shutdown();
螺纹B
public void run() {
try {
//a few business logic lines
MyThreadLocal.set(email);
this.performTask();
} catch (Exception e) {
logger.error( "Error al lanzar thread asincrono: "+ e.getMessage()+" - "+e.getCause() );
e.printStackTrace();
}
}
public void performTask() {
//do stuff in a for loop accessing email with MyThreadLocal.get();
}
当我继续运行主线程时会发生此问题,因为其下一步是刷新整个页面,因此电子邮件设置为新实例,这使我丢失了MyThreadLocal的电子邮件信息
解决方法:
I have two threads using the same Object obj and as I have read every change made in obj by Thread A will be visible for Thread B due to happens-before relationship.
那是不对的.或者至少……这是您编写的不正确1.
现实是,事前发生的关系保证了更新将是可见的.如果没有以前发生的关系,则更改可能是可见的……或者可能不可见.
What I want to do is the opposite, changing obj in Thread A without being visible from Thread B but I have no clue about how to do that.
基本上,您不能保证.如果两个线程正在看同一个对象,则无法阻止一个线程看到另一个线程的更改.
使用线程局部变量没有帮助.
如果您希望一个线程看不到另一个线程对对象所做的更改,则需要复制或克隆该对象,并使两个线程使用不同的副本.
1-(您写的内容暗示A所做的更改始终对B可见,因为存在事前发生的关系.但是不一定有事前发生的关系!我会同意,您可能并不意味着…但是我不知道你不是这个意思,这就是为什么我要脚.
标签:multithreading,happens-before,java 来源: https://codeday.me/bug/20191025/1930754.html