java - ThreadLocal 和非线程安全 API

标签 java multithreading static thread-safety thread-local

所以我有一个我目前正在使用的非线程安全 API(一些供应商软件),我们目前使用它的方式是每个线程一个对象。即每个线程都有:

Foo instance = new Foo();

但是,这似乎不适用于这个特定的库。它的一些非线程安全位似乎仍然令人头疼,所以我假设这个库中有一些静态值。在我们知道它有问题的几个点上,我们目前正在使用 ReentrantLock 在需要时锁定类。即

public class Bar {
    protected static final ReentrantLock lock = new ReentrantLock();

    public void process() {
        Foo instance = new Foo();
        boolean locked = false;
        try{
            if(SomeCondition) {
                locked = true;
                Bar.lock.lock();
            }

            *//rest of the processing goes here

        } finally {
            if(locked){
                Bar.lock.unlock();
            }
        }
    }
}

我的问题是:在这种情况下,所讨论的类不是线程安全的,即使在创建所述类的新实例时,使用锁定更好,还是我应该改用 ThreadLocals? ThreadLocals 会缓解我的实际问题吗?类的 ThreadLocal 版本实际上是否强制类的静态区域本质上是非静态的?

最佳答案

ThreadLocal 所做的只是创建一个查找,每个线程都可以在其中找到自己的对象实例,因此没有线程必须共享。从概念上讲,您可以将其视为以线程 ID 为键的映射。

让每个线程使用自己的对象在某些情况下是一个很好的策略,在 JCIP 书中称为“线程限制”。一个常见的例子是 SimpleDateFormat 对象没有设计成线程安全的,使用它们的并发线程会产生不好的结果。使用 ThreadLocal 可以让每个线程使用自己的 DateFormat,see this question for an example .

但是如果您的问题是对象引用了静态字段,那么这些静态字段存在于类中,而不是实例中,因此使用 ThreadLocal 不会减少共享。

如果您的每个线程都以某种方式使用自己的类加载器,那么每个线程都会有自己的类,并且不会共享其上的静态字段。否则,您对类(class)的锁定似乎是合理的(尽管考虑到您的所有线程都会争用同一个锁,但可能不会很快)。 最好的方法是与供应商合作,让他们修复损坏的代码。

关于java - ThreadLocal 和非线程安全 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37441030/

相关文章:

java - 在 Play 2.4 中循环创建 InputRadioGroups

java - 使用 @ElementCollection : org. hibernate.MappingException : Could not determine type for: java. util.Set 时出错,在表中:对于列

单例上的 C++

java - Apache ActiveMQ 非动态连接到主题

java - 如何初始化静态 List<T>?

java - 关于对象类型的问题

IOS递归分派(dispatch)异步

c# - 我如何获取在 C# 中的线程中运行的操作的返回值?

c - 为什么GCC初始化为0时不分配静态变量

java - jpa hibernate @transactional 配置