简体   繁体   English

ThreadLocal和非线程安全API

[英]ThreadLocal and non-thread safe API

So I have a non-thread safe API (some vendor software) I'm currently using, and the way we're currently using it is one object per thread. 因此,我有一个当前正在使用的非线程安全API(某些供应商软件),而我们当前使用的方式是每个线程一个对象。 ie every thread has: 即每个线程都有:

Foo instance = new Foo();

However, this doesn't appear to work for this particular library. 但是,这似乎不适用于该特定库。 Some non-thread safe bits of it still appear to butt heads, so I'm assuming this library has some static values within it. 它的一些非线程安全位仍然看起来很混乱,因此我假设该库中有一些静态值。 At a few points where we know that it has issues, we currently are using ReentrantLock to lock the class when need be. 在我们知道存在问题的几个点上,我们目前正在使用ReentrantLock在需要时锁定该类。 IE IE

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();
            }
        }
    }
}

My question is: In such an instance where the class in question is NOT thread safe, even when creating new instances of said class, is it better to use locking, or should I look i be using ThreadLocals instead? 我的问题是:在这样的情况下,即使所涉及的类不是线程安全的,即使在创建该类的新实例时,还是最好使用锁定,还是应该使用ThreadLocals? Will ThreadLocals even alleviate my actual issue? ThreadLocals会缓解我的实际问题吗? Does a ThreadLocal version of a class actually force static areas of a class to essentially be non-static? 类的ThreadLocal版本实际上是否强制类的静态区域本质上是非静态的?

All a ThreadLocal does is create a lookup where each thread can find its own instance of an object, so that no threads have to share. ThreadLocal所做的全部工作就是创建一个查找,每个线程都可以找到自己的对象实例,因此不必共享任何线程。 Conceptually you can think of it as a map keyed by thread id. 从概念上讲,您可以将其视为由线程ID键控的映射。

Letting each thread use its own objects is a good strategy for some cases, it's called "thread confinement" in the JCIP book. 在某些情况下,让每个线程使用自己的对象是一个不错的策略,在JCIP书中称为“线程限制”。 A common example of this is that SimpleDateFormat objects were not designed to be thread-safe and concurrent threads using them generated bad results. 一个常见的例子是,SimpleDateFormat对象并非设计为线程安全的,使用它们的并发线程会产生不良结果。 Using a ThreadLocal lets each thread use its own DateFormat, see this question for an example . 使用ThreadLocal可以使每个线程使用其自己的DateFormat, 有关示例请参见此问题

But if your problem is that the object references static fields, then those static fields exist on the class, not on the instance, so using ThreadLocal doesn't do anything to reduce sharing. 但是,如果您的问题是对象引用静态字段,则这些静态字段存在于类中,而不存在于实例中,因此使用ThreadLocal不会做任何减少共享的事情。

If somehow each of your threads used its own classloader then each would have its own class and the static fields on it would not be shared. 如果每个线程以某种方式使用了自己的类加载器,则每个线程将拥有自己的类,并且静态字段不会共享。 Otherwise your locking on the class seems reasonable (though probably not speedy considering all your threads would be contending for the same lock). 否则,您对该类的锁定似乎是合理的(尽管考虑到所有线程都在争夺相同的锁定,这可能并不快)。 The best approach would be working with the vendor to get them to fix their broken code. 最好的方法是与供应商合作,让他们修复损坏的代码。

ThreadLocal will not solve your problem, ThreadLocal simply store different instance for each thread independently. ThreadLocal不会解决您的问题, ThreadLocal只是为每个线程独立存储不同的实例。 so in your case if you have shared resource on your 3 rd party library level that wouldn't solve the problem. 所以你的情况,如果您已经在第三方库的水平,不会解决问题的共享资源。

A simple synchronized monitor will solve the problem, since you want to avoid concurrent access to that library, but be aware of the performance penalty of monitor - only one thread can access the lib concurrently 一个简单的同步监视器将解决该问题,因为您希望避免并发访问该库,但要注意监视器的性能损失-只有一个线程可以并发访问lib

Just do: 做就是了:

public class Bar {
    private static final Object LOCK = new Object();

    public void process() {
        synchronized(LOCK) {
            Foo instance = new Foo();
            instance.myMethod();            
    }
}

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

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