java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同《java并发编程实践》中所说:

写道
给线程安全下定义比较困难。存在很多种定义,如:“一个类在可以被多个线程安全调用时就是线程安全的”。 

静态变量:线程非安全。

静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。

实例变量:单例模式(只有一个对象实例存在)线程非安全,非单例线程安全。

实例变量为对象实例私有,在虚拟机的堆中分配,若在系统中只存在一个此对象的实例,在多线程环境下,“犹如”静态变量那样,被某个线程修改后,其他线程对修改均可见,故线程非安全;如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变量的修改将互不影响,故线程安全。

局部变量:线程安全。

每个线程执行时将会把局部变量放在各自栈帧的工作内存中,线程间不共享,故不存在线程安全问题。

静态变量线程安全问题模拟:

----------------------------------------------------------------------------------

 /**
* 线程安全问题模拟执行
* ------------------------------
* 线程1 | 线程2
* ------------------------------
* static_i = 4; | 等待
* static_i = 10; | 等待
* 等待 | static_i = 4;
* static_i * 2; | 等待
* -----------------------------
* */
public class Test implements Runnable
{
private static int static_i;//静态变量 public void run()
{
static_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取static_i 的值:" + static_i);
static_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取static_i*3的值:" + static_i * );
} public static void main(String[] args)
{
Test t = new Test();
//启动尽量多的线程才能很容易的模拟问题
for (int i = ; i < ; i++)
{
//t可以换成new Test(),保证每个线程都在不同的对象中执行,结果一样
new Thread(t, "线程" + i).start();
}
}
}

根据代码注释中模拟的情况,当线程1执行了static_i = 4;  static_i = 10; 后,线程2获得执行权,static_i = 4; 然后当线程1获得执行权执行static_i * 2;  必然输出结果4*2=8,按照这个模拟,我们可能会在控制台看到输出为8的结果。

写道
[线程27]获取static_i 的值:
[线程22]获取static_i*2的值:
[线程28]获取static_i 的值:
[线程23]获取static_i*2的值:
[线程29]获取static_i 的值:
[线程30]获取static_i 的值:
[线程31]获取static_i 的值:
[线程24]获取static_i*2的值:

看红色标注的部分,确实出现了我们的预想,同样也证明了我们的结论。

实例变量线程安全问题模拟:

----------------------------------------------------------------------------------

 public class Test implements Runnable
{
private int instance_i;//实例变量 public void run()
{
instance_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取instance_i 的值:" + instance_i);
instance_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取instance_i*3的值:" + instance_i * );
} public static void main(String[] args)
{
Test t = new Test();
//启动尽量多的线程才能很容易的模拟问题
for (int i = ; i < ; i++)
{
//每个线程对在对象t中运行,模拟单例情况
new Thread(t, "线程" + i).start();
}
}
}

按照本文开头的分析,犹如静态变量那样,每个线程都在修改同一个对象的实例变量,肯定会出现线程安全问题。

写道

[线程66]获取instance_i 的值:
[线程33]获取instance_i*2的值:
[线程67]获取instance_i 的值:
[线程34]获取instance_i*2的值:
[线程35]获取instance_i*2的值:
[线程68]获取instance_i 的值:

看红色字体,可知单例情况下,实例变量线程非安全。

将new Thread(t, "线程" + i).start();改成new Thread(new Test(), "线程" + i).start();模拟非单例情况,会发现不存在线程安全问题。

局部变量线程安全问题模拟:

----------------------------------------------------------------------------------

 public class Test implements Runnable
{
public void run()
{
int local_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取local_i 的值:" + local_i);
local_i = ;
System.out.println("[" + Thread.currentThread().getName()
+ "]获取local_i*2的值:" + local_i * );
} public static void main(String[] args)
{
Test t = new Test();
//启动尽量多的线程才能很容易的模拟问题
for (int i = ; i < ; i++)
{
//每个线程对在对象t中运行,模拟单例情况
new Thread(t, "线程" + i).start();
}
}
}

控制台没有出现异常数据。

---------------------------------------------------------------

以上只是通过简单的实例来展示静态变量、实例变量、局部变量等的线程安全问题,

并未进行底层的分析,下一篇将对线程问题的底层进行剖析。

静态方法是线程安全的

先看一个类
public class Test{
public static String hello(String str){
String tmp="";
tmp = tmp+str;
return tmp;
}
}
hello方法会不会有多线程安全问题呢?没有!!
静态方法如果没有使用静态变量,则没有线程安全问题。
为什么呢?因为静态方法内声明的变量,每个线程调用时,都会新创建一份,而不会共用一个存储单元。比如这里的tmp,每个线程都会创建自己的一份,因此不会有线程安全问题 注意,静态变量,由于是在类加载时占用一个存储区,每个线程都是共用这个存储区的,所以如果在静态方法里使用了静态变量,这就会有线程安全问题!
总结:只要方法内含有静态变量,就是非线程安全的

java线程安全问题之静态变量、实例变量、局部变量的更多相关文章

  1. (转)java线程安全问题之静态变量、实例变量、局部变量

    java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...

  2. Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序

    实例化子类时,父类与子类中的静态代码块.实例代码块.静态变量.实例变量.构造函数的执行顺序是怎样的? 代码执行的优先级为: firest:静态部分 second:实例化过程 详细顺序为: 1.父类静态 ...

  3. java线程安全问题以及使用synchronized解决线程安全问题的几种方式

    一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...

  4. java线程安全问题原理性分析

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题:如果在整个访问过程中,无一对象被其他线程修改,就是线程安全 ...

  5. java线程安全问题原因及解决办法

    1.为什么会出现线程安全问题 计算机系统资源分配的单位为进程,同一个进程中允许多个线程并发执行,并且多个线程会共享进程范围内的资源:例如内存地址.当多个线程并发访问同一个内存地址并且内存地址保存的值是 ...

  6. Java 线程安全问题的本质

    原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 目录: 线程安全问题的本质 理解CPU JVM虚拟机类比于操作系统 重排序 汇总 一些解释 ...

  7. Java 线程安全问题

    线程安全问题产生原因: 1.多个线程操作共享的数据: 2.操作共享数据的线程代码有多条.   当一个线程正在执行操作共享数据的多条代码过程中,其它线程也参与了运算, 就会导致线程安全问题的发生. cl ...

  8. 3.ruby语法基础,全部变量,实例变量,类变量,局部变量的使用和注意的要点

    1.ruby的全局变量的概念和Java的全局变量的概念不同, ruby的全局变量是以$符号开头的,如果给全局变量的初始化值为nil会出现警告. 赋值给全局变量,这是ruby不推荐的,这样会使程序变得很 ...

  9. iOS中的成员变量,实例变量,属性变量

    在ios第一版中: 我们为输出口同时声明了属性和底层实例变量,那时,属性是oc语言的一个新的机制,并且要求你必须声明与之对应的实例变量,例如: 注意:(这个是以前的用法) @interface MyV ...

随机推荐

  1. python 创建txt并且写入做追加

    import os def create_str_to_txt(self,date,str_data): """ 创建txt,并且写入 """ ...

  2. java多线程15 :wait()和notify() 的生产者/消费者模式

    什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...

  3. UEFI格式预装win8安装win7

    如果本本预装的是win8,而且是较新款的机型,那么当你想要格掉win8,装win7系统时就会遇到问题.主要有两个: 1)安装win7时,笔记本无法识别系统光盘或u盘启动盘 ,提示:屏幕显示“image ...

  4. word中的域代码

    说明(2017-5-23 13:33:11): 1. Shift+F9显示域代码 2. Alt+F9显示全部域代码 3. Ctrl+F9添加一个域代码(一对大括号) 4. Ctrl+Shift+F9取 ...

  5. C++连接Mysql数据库操作

    参考文章 http://www.cnblogs.com/justinzhang/archive/2011/09/23/2185963.html 写的很详细 http://blog.csdn.net/j ...

  6. android studio connot resolve

    使用AS的时候,肯定会遇到这个问题. 我使用清除缓存都不能解决,不过无意中发现代码变了. final Button select = (Button) findViewById(android.R.i ...

  7. jQuery Validate验证方法及教程

    //实名认证 验证 $(function(){ //中文姓名验证 jQuery.validator.addMethod("zh_verify", function(value, e ...

  8. composer概念学习

    composer的中文文档地址 Composer是什么 Composer 是 PHP 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们. Composer 不是一个包管 ...

  9. tomcat添加context方式部署web应用

    刚巧碰到了,记录一下. 通过context的方式部署会灵活一点,不必一定指向tomcat里面的webapps目录 这种部署有几种方式: 1.在$CATALINA_BASE/conf/ server.x ...

  10. Activiti Modeler初探实践

    以下内容对实践activiti很有用,不过我用的不是github下载的源码包编译出来的war包,不知道什么原因我打出来的包会有点问题.不过这不重要,换个地方下载来源就行,下载网址: http://dl ...