简体   繁体   English

Java多线程没有发生之前的关系

[英]Java multithreading without happens-before relationship

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. 我有两个线程使用相同的Object obj ,因为我已经读过Thread Aobj所做的每个更改都将在Thread B显示,因为之前发生关系。

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. 我想做的是相反的,改变Thread A obj而不是从Thread B可见,但我不知道如何做到这一点。

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. 我尝试在Thread B创建一个ThreadLocal ,在run()方法中设置它,并在Thread B使用ThreadLocal.get()而不是obj ,但它一直在读取更改。

Does anyone knows how to achieve this? 有谁知道如何实现这一目标?

Thanks in advance 提前致谢

EDIT: (MVCE) 编辑: (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 线程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 问题发生在我继续运行主线程,因为它的下一步是刷新整个页面,因此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. 我有两个线程使用相同的对象obj,因为我已经读过线程A在obj中所做的每个更改都会因为发生之前的关系而在线程B中可见。

That's not correct. 那不对。 Or at least ... it is not correct as you have written it 1 . 或者至少......它写得不正确1

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. 我想做的是相反的,改变线程A中的obj而不是从线程B可见,但我不知道如何做到这一点。

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.) 1 - (你所写的内容暗示A所做的改变总是对B可见,因为之前发生过关系。但是之前的关系并不一定发生 !我会认为你可能并不意味着 ......但我不知道你不是故意的,这就是我迂腐的原因。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM