我想知道何时声明一个类变量(即在方法外声明的变量)可能会导致由多个线程执行的程序出现问题。我想final
是保存使用(即不共享),并且static
变量肯定在线程之间共享。但是“标准”变量呢?他们什么时候分享,什么时候他们“私密”到每个单独的线程?
更新:虽然我接受局部变量(在方法中)不共享且类变量通常是我想知道为什么(从技术角度来看)。因此,非常感谢任何有关该效果的解释(或链接到相当容易理解的文章)。
答案 0 :(得分:6)
Java提供ThreadLocal<T>
类来声明线程之间不共享的变量。线程之间也不共享非final
参数和局部变量。 final
参数和locals变量可以在线程之间在匿名类定义中使用时共享,但这不应该是一个问题,因为它们是final
。在我能想到的所有其他情况下,变量可以在线程之间共享。
答案 1 :(得分:3)
简短的回答是,static
和非static
的任何方法或变量,如果其访问修饰符使其可见,则有可能被多个Thread
访问那个Thread
。
“线程安全”的概念完全不同。如果变量是只读的(final
可用于使基元只读,但只引用对象不可变,而不是对象本身),该变量的多线程访问本质上是线程安全的。如果可以写入,则必须正确使用synchronized
块或volatile
关键字以确保互斥。
答案 2 :(得分:0)
最终并不意味着'不共享'只是该字段不能被覆盖,它只能被初始化一个。 静态行为也与线程无关,静态意味着该字段具有Class范围而非实例范围,这意味着它由Class的所有实例共享。 如果要保护字段不被许多线程修改,则必须通过同步方法对其进行操作。
答案 3 :(得分:0)
这些变量被称为类的 fields ,它们通常是不“线程安全”,即使它们是final
(因为final
仅引用引用本身,而不引用对象内部的内容。
答案 4 :(得分:0)
标准变量没有什么特别之处可以保护它免受多线程访问和导致的问题的影响。这取决于程序员担心的问题。
如果两个线程需要安全地访问相同的实例字段,那么您必须编写代码来管理它。
一些常见的技术是使用synchronized块来管理可变性,使用原子或最终原语(除非你知道Object不可变,否则最终的Object不一定是安全的),或者只是使用ThreadLocal为每个线程提供自己的非共享的类实例。