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.
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.
I have tried creating a ThreadLocal
in Thread B
, setting it in run()
method, and using ThreadLocal.get()
instead of obj
in Thread B
but it keeps reading the changes.
Does anyone knows how to achieve this?
Thanks in advance
EDIT: (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();
}
}
Main Thread
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();
Thread 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();
}
The issue happens when I keep running the main thread since its next step is refreshing the whole page so email
is set to a new instance, which makes me lose MyThreadLocal's email information
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.
That's not correct. Or at least ... it is not correct as you have written it1.
The reality is that a happens-before relationship guarantees that updates will be visible. If there is no happens-before relationship, then the changes might be visible ... or they might be NOT visible.
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.
Basically, you cannot guarantee it. If two threads are looking at the same object, then there is no way to STOP one thread from seeing changes by the other.
Using thread-local variables doesn't help.
If you want one thread to not see the changes made to an object by the other thread, then you need to copy or clone the object and have the two threads use different copies.
1 - (What you wrote implies that a change made by A will always be visible to B because there is a happens-before relationship. But there isn't necessarily a happens-before relationship! I will grant that you may not have meant that ... but I don't know that you didn't mean it, which is why I am being pedantic.)