使用 ThreadLocal使普通类成为线程安全的
我有一个普通的类,设计为由单个线程访问,我想使其成为线程安全的,以便许多线程可以同时使用单个实例。我会将一些类级方法和变量设为静态,并使用锁
使它们成为线程安全
。默认情况下,仅使用局部变量的方法也是安全的(每个线程都有其堆栈)。
我的问题是关于旧类的属性或更普遍的任何非静态变量。我可以简单地使用 ThreadLocal属性
吗?当然,我会在 setters
中使用锁
和其他线程安全
问题(我假设getters
是安全的)。
ThreadLocal
I have a normal class designed to be accessed by a single thread and I want to make it thread-safe
so many threads can use a single instance at the same time. There are some class level methods and variables which I will make static and using locks
make them thread-safe
. Also methods which only use local variables are safe (each thread has it's stack) by default.
My question it about properties
of the old class or more generally any non-static
variable. Can I simply use ThreadLocal<T>
and each thread has it's own set of properties
? Surely I will use locks
and other thread-safety
issues inside setters
(I assume getters
are safe).
And is ThreadLocal<T>
performance killer ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Getters 并不像你想象的那么安全。 Java 内存模型为每个线程提供了自己的堆视图,因此如果不同步对变量的访问,则线程可能会读取过时的数据。使变量
易失性
将防止过时读取,并且对于原语来说很好,但易失性
不会使访问原子化。java.util.concurrent
包中的许多类可能会帮助您。编写线程安全代码很棘手,因此我建议您阅读一本关于该主题的好书。 Brian Goetz 的《Java 并发实践》相当不错。Getters are not as safe as you think. The Java memory model gives each thread it's own view of the heap, so if you don't synchronize access to variables then threads may read stale data. Making a variable
volatile
will prevent stale reads and is fine for primitives, butvolatile
won't make access atomic.There are a bunch of classes in the
java.util.concurrent
package that might help you out. Writing thread-safe code is tricky, so I'd recommend getting a good book on the subject. Brian Goetz's "Java concurrency in practice" is pretty good.这并不是线程局部变量的真正用途。它们适用于每个线程都有自己的数据的情况。
对于您的情况,我建议将字段类型更改为
Map
并使用Collections.synchronizedMap
使其线程安全。That's not really what thread locals are for. They're intended for cases where each thread will have its own data.
In your case, I would suggest changing the field type to
Map<Object, Object>
and usingCollections.synchronizedMap
to to make it thread safe.