哪些情况下 静态变量什么是线程安全全的

转自:http://blog.csdn.net/yy/article/details/
有时候,对于在多线程中使用static变量有没有冲突,是否存在安全问题不能十分的确定。在使用过程中有点含糊,总想找点时间好好追究一下,可总因开发项目时间的紧迫而搁浅。我想,没有做进一步的研究而拿项目繁忙说事,这是自己的借口吧!
&&&&鲁迅先生曾说过:“时间就像海绵里的水,只要愿挤,总还是有的”。不管肿(怎)么说,这事还是要做的啊。如果越往后推,可能造成的潜在影响更大。这始终是个隐患,不能不除。
&&&&不是痛定思痛,而是认识到事情的重要性,就要开始行动了... ...
&&&&&以上是个人的闲言碎语,不足而看。下面,我们就少言几句进入到技术领域吧!
&&&&线程,是我们项目中绕不过的重点领域。提到线程,就常会听到线程安全的术语。那什么是线程安全呢?通俗点说,就是线程访问时不产生资源冲突。其实,这是一个有点难以定义的概念,不是很容易让人一听就懂的概念。“一个类可以被多个线程安全调用就是线程安全的”《编程并发实践》。
&&&&来说说静态变量、实例变量、局部变量在多线程下的安全问题吧!
&&&&(一)静态变量:线程非安全
&& 1、静态变量:使用static关键字定义的变量。static可以修饰变量和方法,也有static静态代码块。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
&&&&用public修饰的static成员变量和成员方法本质是变量和全局方法,当声明它的类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。
&&&&2、静态变量使用的场景:
&&& (1)对象间共享值时
&&& (2)方便访问变量时
&&&&3、静态方法使用注意事项:
&&& (1)不能在静态方法内使用非静态变量,即不能直接访问所属类的实例变量;
&&& (2)不能在静态方法内直接调用非静态方法;
&&& (3)静态方法中不能使用this和super关键字;
&&&&4、验证静态变量的线程安全性:
&&&&(1)从程序执行的图中我们可以看出,执行结果中有错误数据,证明了静态变量是存在资源冲突问题的。
&&& (2)程序运行结果图:&
&&&&5、结论:静态变量也称为类变量,属于类对象所有,位于方法区,为所有对象共享,共享一份内存,一旦值被修改,则其他对象均对修改可见,故线程非安全。
&&&&(二)实例变量:单例时线程非安全,非单例时线程安全
&&&&1、实例变量:实例变量属于类对象的,也就是说,属于对象实例私有,在虚拟机的堆中分配。
&&&&2、验证实例变量的线程安全性:
&&&&(1)从程序截图中,我们可以看到,当为单例模式时,会产生资源冲突,当非单例模式时,则不会产生线程冲突。
&&& (2)程序运行结果图:
&3、结论:实例变量是实例对象私有的,系统只存在一个实例对象,则在多线程环境下,如果值改变后,则其它对象均可见,故线程非安全;如果每个线程都在不同的实例对象中执行,
则对象与对象间的修改互不影响,故线程安全。
&&&&(三)局部变量:线程安全
&&&& 1、局部变量:定义在方法内部的变量。
&&&& 2、验证局部变量的安全性:
&&&&(1)从程序截图中可以看出,局部变量在多线程下没有产生资源冲突的问题
&&& (2)程序运行结果图:
&&& 3、结论:每个线程执行时都会把局部变量放在各自的帧栈的内存空间中,线程间不共享,故不存在线程安全问题。
&&&&(四)静态方法的线程安全性
&&&&&1、静态方法中如果没有使用静态变量,则没有线程安全的问题;
&&&&&&&&& 静态方法内的变量,每个线程调用时,都会新创建一份,不会公用一个存储单元,故不存在线程冲突的问题。
&&&&以上就是对多线程环境下静态变量、实例变量和局部变量的一点点研究,也仅供自己在需要或遗忘的时候查询参考下了。
阅读(...) 评论()15:18 提问
Java中静态方法的线程安全问题
Java中多个线程同时访问一个静态方法是否存在线程安全问题?
比如以下代码,两个线程同时对方法中b修改不同的值,会有线程安全问题吗?
new Thread(new Runnable()
public void run()
}).start();
new Thread(new Runnable()
public void run()
}).start();
static void fun(int a)
int b = 100;
for (int i=0; i&100; i++)
System.out.println(Thread.currentThread().getName() + "--&" + b);
按赞数排序
是不是线程安全取决于这个静态方法内部是否调用了线程不安全的方法,不安全的成员变量,并且没有同步。
如果没有调用任何方法,只调用局部变量,就是安全的。
但静态方法不是内存中只有一份,而且方法中的局部变量也只有一份?
静态方法不存在线程安全问题,只有涉及到全局共享变量的操作时才需要关注线程安全问题。
总的结论:java是线程安全的,即对任何方法(包括静态方法)都可以不考虑线程冲突,但有一个前提,就是不能存在全局变量。如果存在全局变量,则需要使用同步机制。
如下通过一组对比例子从头讲解:
在多线程中使用静态方法会发生什么事?也就是说多线程访问同一个类的static静态方法会发生什么事?是否会发生线程安全问题?
public class Test {
public static void operation(){
// ... do something
事实证明只要在静态函数中没有处理多线程共享数据,就不存在着多线程访问同一个静态方法会出现资源冲突的问题。下面看一个例子:
public class StaticThread implements Runnable {
public void run() {
// TODO Auto-generated method stub
StaticAction.print();
public static void main(String[] args) {
for (int i = 0; i & 100; i++) {
new Thread(new StaticThread()).start();
public class StaticAction {
public static int i = 0;
public static void print() {
int sum = 0;
for (int i = 0; i & 10; i++) {
System.out.print("step " + i + " is running.");
if (sum != 45) {
System.out.println("Thread error!");
System.exit(0);
System.out.println("sum is " + sum);
实际执行的结果显示各个线程对静态方法的访问是交叉执行的,但是这并不影响各个线程静态方法print()中sum值的计算。也就是说,在此过程中没有使用全局变量的静态方法在多线程中是安全的,静态方法是否引起线程安全问题主要看该静态方法是否对全局变量(静态变量static member)进行修改操作。
在多线程中使用同一个静态方法时,每个线程使用各自的实例字段(instance field)的副本,而共享一个静态字段(static field)。所以说,如果该静态方法不去操作一个静态成员,只在方法内部使用实例字段(instance field),不会引起安全性问题。
但是,如果该静态方法操作了一个静态变量,则需要静态方法中采用互斥访问的方式进行安全处理。我们来看一下没有使用互斥访问的话会产生怎样的问题:public class StaticAction {
public static int i = 0;
public static void incValue() {
int temp = StaticAction.i;
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
StaticAction.i =
public class StaticThread implements Runnable {
public void run() {
// TODO Auto-generated method stub
StaticAction.incValue();
public static void main(String[] args) {
for (int i = 0; i & 100; i++) {
new Thread(new StaticThread()).start();
Thread.sleep(1000); //预留足够的时间让上面的线程跑完
} catch (Exception e) {
e.printStackTrace();
System.out.println(StaticAction.i);
实际运行结果显示i值为随机的数字。为了实现互斥访问,这时我们需要加入一个synchronized关键字。代码修改如下:
public class StaticAction {
public static int i = 0;
public synchronized static void incValue() {
int temp = StaticAction.i;
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
StaticAction.i =
public class StaticThread implements Runnable {
public void run() {
// TODO Auto-generated method stub
StaticAction.incValue();
public static void main(String[] args) {
for (int i = 0; i & 100; i++) {
new Thread(new StaticThread()).start();
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
System.out.println(StaticAction.i);
运行结果则必然是100。
加入synchronized关键字的静态方法称为同步静态方法。
在访问同步静态方法时,会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。这个其实就是操作系统中的用信号量实现进程的互斥与同步问题,如果涉及在同一个类中有多个静态方法中处理多线程共享数据的话,那就变成用信号量解决生产者-消费者问题。也就是说,静态方法是一份临界资源,对静态方法的访问属于进入临界区;对静态变量的修改是一份临界资源,对静态变量的修改属于进入临界区。
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐java中的线程安全是什么?什么叫线程安全?什么叫不安全?_百度知道
该问题可能描述不清,建议你
java中的线程安全是什么?什么叫线程安全?什么叫不安全?
我有更好的答案
java中的线程安全是什么:
就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问什么叫线程安全:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
打个比方:一个蛋糕,几个人一起吃。第一种情况:当一个人吃的时候其他人要等这个人吃完才能吃。(线程安全)第二种情况:几个人一起上,同时吃。(线程不安全)
就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问什么叫线程安全:
存在竞争的线程不安全,不存在竞争的线程就是安全的
他们的解释都很正确。
其他2条回答
为您推荐:
其他类似问题
您可能关注的内容
线程安全的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。多线程中相同变量的访问冲突问题(转)
http://www.cnblogs.com/doit8791/p/4093808.html
线程同步机制:在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
ThreadLocal :
ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。&
多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的。&&
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
1) 常量始终是线程安全的,因为只存在读操作。&
2)每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
3)局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象
&,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象
&.不能保存数据,是不变类,是线程安全的。
有状态对象:
无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype:
每次对bean的请求都会创建一个新的bean实例。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。函数里的static变量初始化是线程安全的吗_百度知道
函数里的static变量初始化是线程安全的吗
我有更好的答案
  静态局部变量具有局部作用域。它只被初始化一次,自从第一次初始化直到程序与你新内阁结束都一直存在,他和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。   各个变量的比较区别。     从作用域看:     全局变量和局部变量:全局变量和局部变量的区别主要在于身存周期不同,全局变量在整个程序生成期可见,局部变量在自己的作用域可见。全局变量的内存分配是静态的,如果没有赋初值,会被初始化为0。局部变量的内存分配是动态的,位于堆栈中,如果没有初始化,初值视当前内存内的值而定。     全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包括全局变量定义的源文件需要用extern关键字再次声明这个全局变量。     静态全局变量也具有全局作用域,他与全局变量的区别在于如果程序包含多个文件的话,他作用于定义它的文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同的静态全局变量,他们也是不同的变量。     局部变量也只有局部作用域,他是自动对象,他在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用结束后,变量就被撤销,其所占用的内存也被收回。     静态局部变量具有局部作用域。它只被初始化一次,自从第一次初始化直到程序与你新内阁结束都一直存在,他和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。     从内存分配看:     全局变量、静态局部变量、静态全局变量都在静态存储区分配空间,而局部变量在栈分配空间。     全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上没有什么不同。区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。     一、静态变量会被放在程序的静态数据存储区里,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是他与堆栈变量和堆变量的区别     二、变量用static告知编译器,自己仅仅在变量的作用域范围内可见。这一点是他与全局变量的区别。     从以上分析可以看出,把局部变量改变为静态变量后是改变了他的存储方式,即改变了他的生存期。把全局变量改变为静态变量后是改变了他的作用域,限制了他的使用范围,因此static这个说明符在不同的地方起的作用是不同的。     不同类型的变量在内存中的位置:     一、 已经初始化的全局变量存放与data数据段;未初始化的全局变量存放与bss数据段。     二、 静态的全局变量存放与data数据段     三、 局部变量存放在栈上。     四、 静态局部变量,并不是在调用函数时分配函数返回时释放,而是像全局变量一样静态分配,存放data数据段,但它的作用域在函数中起作用。         下图是内存中的简要分布图,可以更直观的理解个类型变量在内存中的存放位置,图一
采纳率:59%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 什么情况下使用静态变量 的文章

 

随机推荐