Ana*_*and 86 java thread-safety
我正在阅读Java中的多线程,我遇到了这个问题
局部变量在Java中是线程安全的.
从那时起,我一直在思考如何/为什么局部变量是线程安全的.
有人可以让我知道.
kos*_*osa 97
创建线程时,它将创建自己的堆栈.两个线程将有两个堆栈,一个线程永远不会与其他线程共享其堆栈.
在你的程序中定义的所有局部变量将被分配在堆栈存储器(如Jatin评论,这里存储装置,对象和基本类型值的参考值)(由主题中的每个方法调用创建其自己的堆栈一个堆栈帧).一旦该线程完成方法执行,就会删除堆栈帧.
斯坦福教授在youtube上有很棒的演讲,可以帮助你理解这个概念.
Ren*_*ith 17
局部变量存储在每个线程自己的堆栈中.这意味着线程之间永远不会共享局部变量.这也意味着所有本地原始变量都是线程安全的.
public void someMethod(){
long threadSafeInt = 0;
threadSafeInt++;
}
Run Code Online (Sandbox Code Playgroud)
对象的本地引用有点不同.引用本身不共享.但是,引用的对象不存储在每个线程的本地堆栈中.所有对象都存储在共享堆中.如果本地创建的对象永远不会转义它创建的方法,那么它是线程安全的.实际上,只要这些方法或对象都不会将传递的对象提供给其他线程,您也可以将其传递给其他方法和对象.
Cor*_*all 14
想一想像功能定义这样的方法.当两个线程运行相同的方法时,它们绝不相关.他们每个人都会创建自己的每个局部变量版本,并且无法以任何方式相互交互.
如果变量不是本地的(例如在类级别的方法之外定义的实例变量),那么它们将附加到实例(而不是单个方法的运行).在这种情况下,运行相同方法的两个线程都看到一个变量,这不是线程安全的.
考虑这两种情况:
public class NotThreadsafe {
int x = 0;
public int incrementX() {
x++;
return x;
}
}
public class Threadsafe {
public int getTwoTimesTwo() {
int x = 1;
x++;
return x*x;
}
}
Run Code Online (Sandbox Code Playgroud)
在第一个中,在同一个实例上运行的两个线程NotThreadsafe
将看到相同的x.这可能很危险,因为线程正试图改变x!在第二个,在同一个实例上运行的两个线程Threadsafe
将看到完全不同的变量,并且不会相互影响.
除了Nambari的其他答案.
我想指出你可以在anoymous类型方法中使用局部变量:
可以在其他线程中调用此方法,这可能会损害线程安全性,因此java会强制将在anoymous类型中使用的所有局部变量声明为final.
考虑这个非法代码:
public void nonCompilableMethod() {
int i=0;
for(int t=0; t<100; t++)
{
new Thread(new Runnable() {
public void run() {
i++; //compile error, i must be final:
//Cannot refer to a non-final variable i inside an
//inner class defined in a different method
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
如果java允许这样做(就像C#通过"闭包"那样),那么局部变量在所有情况下都不再是线程安全的.在这种情况下,i
不保证所有线程结尾的值100
.
每个方法调用都有自己的局部变量,显然,方法调用发生在一个线程中.仅由单个线程更新的变量本质上是线程安全的.
但是,请密切关注这究竟是什么意思:只有对变量本身的写入是线程安全的; 在它引用的对象上调用方法本身并不是线程安全的.直接更新对象的变量也是如此.
归档时间: |
|
查看次数: |
42309 次 |
最近记录: |