Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ThreadLocal和非线程安全API_Java_Multithreading_Static_Thread Safety_Thread Local - Fatal编程技术网

Java ThreadLocal和非线程安全API

Java ThreadLocal和非线程安全API,java,multithreading,static,thread-safety,thread-local,Java,Multithreading,Static,Thread Safety,Thread Local,因此,我有一个非线程安全API(一些供应商软件),我目前正在使用,我们目前使用的方式是每个线程一个对象。i、 e.每根线都有: Foo instance = new Foo(); 然而,这似乎不适用于这个特定的库。它的一些非线程安全的部分仍然看起来像是对头,所以我假设这个库中有一些静态值。在我们知道它有问题的一些地方,我们目前正在使用ReentrantLock在需要时锁定类。即 public class Bar { protected static final ReentrantLoc

因此,我有一个非线程安全API(一些供应商软件),我目前正在使用,我们目前使用的方式是每个线程一个对象。i、 e.每根线都有:

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?这会缓解我的实际问题吗?类的ThreadLocal版本实际上是否强制类的静态区域本质上是非静态的?

ThreadLocal所做的只是创建一个查找,其中每个线程都可以找到自己的对象实例,因此线程不必共享。从概念上讲,您可以将其视为由线程id设置密钥的映射

在某些情况下,让每个线程使用自己的对象是一种很好的策略,在JCIP书中称之为“线程限制”。一个常见的例子是SimpleDataFormat对象不是设计为线程安全的,使用它们的并发线程会产生不好的结果。使用ThreadLocal允许每个线程使用自己的DateFormat

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

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

ThreadLocal
不会解决您的问题,
ThreadLocal
只是为每个线程单独存储不同的实例。因此,在您的情况下,如果您在第三方库级别共享了资源,这并不能解决问题

一个简单的同步监视器可以解决这个问题,因为您希望避免并发访问该库,但要注意监视器的性能损失——只有一个线程可以并发访问该库

只要做:

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

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

不,ThreadLocal不强制类的静态区域本质上是非静态的,为什么您认为
ThreadLocal
对每个线程中的本地对象的行为会有所不同?@StrangerintheQ-好吧,那么,我想这回答了我的问题如果您已经在每个线程中使用实例,那么供应商代码是线程敌对的,不仅仅是线程不安全。与其使用
ReentrantLock
,不如使用代理包装类,使所有方法
同步,然后在所有线程中使用该实例。这很有意义。谢谢你的意见!是的,我一直在探索这一点,因为锁定不一定很快,所以我希望它能在这个部门有所帮助。即使是静态锁定也不能保证它能正常工作。根据通过静态变量跟踪的信息的不同,您仍然可以在线程之间获得隐藏的信息。@jtahlborn:对,锁定粒度可能必须非常广泛,从而使多线程变得毫无意义。我将调查自定义类加载器的角度。