【问题标题】:Synchronized with ThreadLocal vs InheritableThreadLocal?与 ThreadLocal 与 InheritableThreadLocal 同步?
【发布时间】:2012-10-26 07:18:04
【问题描述】:

我正在按照 thread local pattern 实现一个 vaadin 应用程序。

应用程序的状态由多个工作线程修改。因此,为了通知应用程序其状态已更改,我添加了一个进度指示器。

阅读进度指示器示例,我看到了:

        // All modifications to Vaadin components should be synchronized
        // over application instance. For normal requests this is done
        // by the servlet. Here we are changing the application state
        // via a separate thread.
        synchronized (getApplication()) {
            prosessed();
        }

所以基本上,我想我只需修改对getApplication 的调用即可获取我的应用程序实例(只需调用getCurrent):

  private static ThreadLocal<MyApplication> currentApplication = new ThreadLocal<MyApplication>();

    @Override
    public void init() {
        setCurrent(this); // So that we immediately have access to the current application

        // initialize mainWindow and other stuff

        // Register a transaction listener that updates our ThreadLocal with each request
        if (getContext() != null) {
            getContext().addTransactionListener(this);
        }   
    }

    /**
     * @return the current application instance
     */
    public static MyApplication getCurrent() {
        return currentApplication.get();
    }

问题是我的工作线程死于饥饿,因为它无法获取应用程序上的互斥锁。 vaadin 论坛提供的一种解决方案是使用InheritableThreadLocal。它有效,但我不明白为什么。

来自 javadoc:

这个类扩展了 ThreadLocal 以提供值的继承 父线程到子线程:创建子线程时, child 接收所有可继承线程本地的初始值 父级具有值的变量。通常孩子的价值观 将与父母的相同;但是,孩子的价值可以是 通过重写父级的任意函数 此类中的 childValue 方法。

优先使用可继承的线程局部变量 维护每个线程属性时的线程局部变量 在变量(例如,用户 ID、交易 ID)中必须自动 传输到任何创建的子线程。

我的工作线程无法获得锁,因为它没有接收到初始值? 我误解了什么吗? 除了this problem,我应该注意使用 InheritableThreadLocal 的潜在陷阱是什么?

谢谢。

【问题讨论】:

    标签: java multithreading concurrency vaadin


    【解决方案1】:

    理解其工作原理的关键是 ThreadLocal 类中的方法:

    static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
       return new ThreadLocalMap(parentMap);
    }
    

    它被设计为只能从 Thread 构造函数中调用。方法

    protected Object childValue(Object parentValue)
    

    InheritableThreadLocal 类用于将子线程中InheritableThreadLocal 变量的初始值设置为父线程中ThreadLocal 变量(作为参数传递)的函数。在创建子线程之前从父线程中调用此方法,默认实现将使子值与父值相同,但我们可以重写 childValue() 方法将子值设置为父值的函数那些在父线程中有值的ThreadLocals。默认情况下,childValue() 返回相同的输入参数,但再次覆盖 childValue() 方法也可能会改变这种行为。

    所以InheritableThreadLocal 的工作方式几乎与ThreadLocal 一样,并且具有相同的同步缺陷。

    【讨论】:

    • 我不太明白,尤其是最后一句话以“So”开头。我不明白为什么这是上一段的结果。为什么饥饿与 ThreadLocal 而不是 InheritableThreadLocal ?
    猜你喜欢
    • 2014-03-20
    • 2016-08-28
    • 1970-01-01
    • 2021-09-27
    • 2012-01-17
    • 2011-07-19
    • 2015-11-05
    • 1970-01-01
    相关资源
    最近更新 更多