Java 没有 happens-before 关系的多线程
Java multithreading without happens-before relationship
我有两个使用相同 Object obj
的线程,正如我所读,Thread A
在 obj
中所做的每项更改都将对 Thread B
可见,因为发生了 -关系之前。
我想做的恰恰相反,在 Thread A
中更改 obj
而 Thread B
不可见,但我不知道该怎么做。
我尝试在 Thread B
中创建一个 ThreadLocal
,在 run()
方法中设置它,并在 [=17] 中使用 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();
}
当我保留 运行 主线程时会出现问题,因为它的下一步是刷新整个页面,因此 email
被设置为一个新实例,这让我丢失了 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.
现实情况是 happens-before 关系保证更新可见。如果没有 happens-before 关系,那么更改可能是可见的......或者它们可能是不可见的。
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 可见,因为 发生了- before 关系。但不一定存在 happens-before 关系!我承认你可能没有 meant ...但我不知道你不是那个意思,这就是我迂腐的原因。)
我有两个使用相同 Object obj
的线程,正如我所读,Thread A
在 obj
中所做的每项更改都将对 Thread B
可见,因为发生了 -关系之前。
我想做的恰恰相反,在 Thread A
中更改 obj
而 Thread B
不可见,但我不知道该怎么做。
我尝试在 Thread B
中创建一个 ThreadLocal
,在 run()
方法中设置它,并在 [=17] 中使用 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();
}
当我保留 运行 主线程时会出现问题,因为它的下一步是刷新整个页面,因此 email
被设置为一个新实例,这让我丢失了 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.
现实情况是 happens-before 关系保证更新可见。如果没有 happens-before 关系,那么更改可能是可见的......或者它们可能是不可见的。
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 可见,因为 发生了- before 关系。但不一定存在 happens-before 关系!我承认你可能没有 meant ...但我不知道你不是那个意思,这就是我迂腐的原因。)