转载

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

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

此处不赘述了,首先给出静态变量、实例变量、局部变量在多线程环境下线程安全问题结论,然后用示例验证,请大家擦亮眼睛,有错必究,否则误人子弟!

静态变量:线程非安全。

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

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

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

局部变量:线程安全。

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

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

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

Java代码  
  1. /**
  2. * 线程安全问题模拟执行
  3. *  ------------------------------
  4. *       线程1      |    线程2
  5. *  ------------------------------
  6. *   static_i = 4;  | 等待
  7. *   static_i = 10; | 等待
  8. *    等待          | static_i = 4;
  9. *   static_i * 2;  | 等待
  10. *  -----------------------------
  11. * */
  12. public class Test implements Runnable
  13. {
  14. private static int static_i;//静态变量
  15. public void run()
  16. {
  17. static_i = 4;
  18. System.out.println("[" + Thread.currentThread().getName()
  19. + "]获取static_i 值:" + static_i);
  20. static_i = 10;
  21. System.out.println("[" + Thread.currentThread().getName()
  22. + "]获取static_i*3值:" + static_i * 2);
  23. }
  24. public static void main(String[] args)
  25. {
  26. Test t = new Test();
  27. //启动尽量多线程才能很容易模拟问题
  28. for (int i = 0; i < 3000; i++)
  29. {
  30. //t可以换成new Test(),保证每个线程都在不同对象中执行,结果一样
  31. new Thread(t, "线程" + i).start();
  32. }
  33. }
  34. }

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

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

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

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

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

Java代码  
  1. public class Test implements Runnable
  2. {
  3. private int instance_i;//实例变量
  4. public void run()
  5. {
  6. instance_i = 4;
  7. System.out.println("[" + Thread.currentThread().getName()
  8. + "]获取instance_i 值:" + instance_i);
  9. instance_i = 10;
  10. System.out.println("[" + Thread.currentThread().getName()
  11. + "]获取instance_i*3值:" + instance_i * 2);
  12. }
  13. public static void main(String[] args)
  14. {
  15. Test t = new Test();
  16. //启动尽量多线程才能很容易模拟问题
  17. for (int i = 0; i < 3000; i++)
  18. {
  19. //每个线程对在对象t中运行,模拟单例情况
  20. new Thread(t, "线程" + i).start();
  21. }
  22. }
  23. }

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

写道

[线程66]获取instance_i 值:10 
[线程33]获取instance_i*2值:20 
[线程67]获取instance_i 值:4 
[线程34]获取instance_i*2值:8 
[线程35]获取instance_i*2值:20 
[线程68]获取instance_i 值:4

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

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

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

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

Java代码  
  1. public class Test implements Runnable
  2. {
  3. public void run()
  4. {
  5. int local_i = 4;
  6. System.out.println("[" + Thread.currentThread().getName()
  7. + "]获取local_i 值:" + local_i);
  8. local_i = 10;
  9. System.out.println("[" + Thread.currentThread().getName()
  10. + "]获取local_i*2值:" + local_i * 2);
  11. }
  12. public static void main(String[] args)
  13. {
  14. Test t = new Test();
  15. //启动尽量多线程才能很容易模拟问题
  16. for (int i = 0; i < 3000; i++)
  17. {
  18. //每个线程对在对象t中运行,模拟单例情况
  19. new Thread(t, "线程" + i).start();
  20. }
  21. }
  22. }

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

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

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

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

静态方法是线程安全

先看一个

public class  Test{

public static  String hello(String str){

String tmp="";

tmp  =  tmp+str;

return tmp;

}

}

hello方法会不会有多线程安全问题呢?没有!!

静态方法如果没有使用静态变量,则没有线程安全问题。

为什么呢?因为静态方法内声明变量,每个线程调用时,都会新创建一份,而不会共用一个存储单元。比如这里tmp,每个线程都会创建自己一份,因此不会有线程安全问题

注意,静态变量,由于是在加载时占用一个存储区,每个线程都是共用这个存储区,所以如果在静态方法里使用了静态变量,这就会有线程安全问题!

总结:只要方法内含有静态变量,就是非线程安全

java线程安全问题之静态变量、实例变量、局部变量相关推荐

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

    2019独角兽企业重金招聘Python工程师标准>>> java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编 ...

  2. Java 线程池详解及实例代码

    转载自  Java 线程池详解及实例代码 这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下 线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时 ...

  3. 关于如何解决java线程安全问题?很重要? 快拿小本本记下来!

    关于如何解决java线程安全问题?很重要? 快拿小本本记下来! 线程安全问题 什么是线程安全问题? 线程同步 同步代码块 同步方法 lock显示锁 线程安全问题 什么是线程安全问题? 多个线程操作同一 ...

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

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

  5. java静态变量实例变量_java中静态变量和实例变量的区别

    实例变量:只有在创建了实例对象之后才会被分配空间,才可以使用 静态变量:不需要创建实例对象就可以直接使用类名进行引用 public class Different { public static in ...

  6. 静态与实例变量的区别——(面试题)

    静态变量与实例变量(方法)的区别 这道题主要考察的是我们对于static静态关键字是如何理解的(分为以下三点) 一.语法区别: 静态变量前要加static关键字,实例则不用 二.隶属区别: 实例变量属 ...

  7. 静态与实例变量的区别——(概述)

    静态变量与实例变量(方法)的区别 这道题主要考察的是我们对于static静态关键字是如何理解的(分为以下三点) 一.语法区别: 静态变量前要加static关键字,实例则不用 二.隶属区别: 实例变量属 ...

  8. Java基础篇:隐藏的实例变量

    有时一个方法需要引用调用它的对象.为此,Java定义了this这个关键字.this可以在引用当前对象的所有方法内使用.也就是,this总是调用该方法对象的一个引用.你可以在当前类的类型所允许对象的任何 ...

  9. JAVA线程安全问题

    卖票的过程中出现了线程安全问题,有重票和错票的问题.为什么会出现这个问题?当某个线程在操作卖票的过程中尚未完成卖票操作,其他线程也参与进来操作卖票,就会出现线程安全问题,(主要是共享数据(nums)的 ...

最新文章

  1. uboot引导kernel - 3 -uboot给内核传参详解
  2. 大满贯!清华学生超算团队获得国际大学生超级计算机竞赛(SC18)总冠军(附现场视频)...
  3. 理解 iOS 和 macOS 的内存管理
  4. 【David Silver强化学习公开课】-7:Policy Gradient
  5. 全国计算机等级考试题库二级C操作题100套(第51套)
  6. ansible puppet saltstack三款自动化运维工具的对比
  7. Hexo-theme-Fluid Material Design 风格的 Hexo 主题
  8. 《精通Spring4.X企业应用开发实战》读后感第四章(Java反射)
  9. HALCON: 本地程序函数(.hdev或.dev)、HDevelop函数文件或外部函数(.hdvp)及库函数(.hdpl)使用详解
  10. golang编译之vendor机制
  11. 【3D文件格式解析】.obj + .mtl
  12. 外贸常见的付款方式你了解吗?
  13. 利用python进行身份证号码大全_身份证号码设置显示格式,我用了最笨的办法,你有什么好办法吗?...
  14. php解析酷狗音乐,PHP_将酷狗krc歌词解析并转换为lrc歌词php源码,最近在进行一次对酷狗音乐歌 - phpStudy...
  15. Vim插件推荐--模糊搜索插件ctrlp使用方法
  16. vue面试题+答案,2021前端面试
  17. 添加分隔符|的几种方法
  18. postman——集合——执行集合——脚本的执行顺序——验证
  19. Excel 2010 VBA 入门 037 获取最后一行数据的行数
  20. 曾国藩:一勤天下无难事(五勤)

热门文章

  1. 浏览器title中的小图标0927 0928
  2. HDU-4417 Super Mario
  3. BZOJ 1188: [HNOI2007]分裂游戏(multi-nim)
  4. javascript有用小功能总结(未完待续)
  5. Java Spring MVC
  6. Google Code Jam Round 1A 2015 解题报告
  7. shell脚本实现无密码交互的SSH自动登陆
  8. Andriod: 在xml布局中使用自定义属性
  9. vue-cli 新建模板项目---vue-cli
  10. Win7下Anaconda3+Tensorflow