Java ThreadLocal和非线程安全API
因此,我有一个非线程安全API(一些供应商软件),我目前正在使用,我们目前使用的方式是每个线程一个对象。i、 e.每根线都有: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
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:对,锁定粒度可能必须非常广泛,从而使多线程变得毫无意义。我将调查自定义类加载器的角度。