• Java多线程中static变量的使用


    有时候,对于在多线程中使用static变量有没有冲突,是否存在安全问题不能十分的确定。在使用过程中有点含糊,总想找点时间好好追究一下,可总因开发项目时间的紧迫而搁浅。

        线程,是我们项目中绕不过的重点领域。提到线程,就常会听到线程安全的术语。那什么是线程安全呢?通俗点说,就是线程访问时不产生资源冲突。其实,这是一个有点难以定义的概念,不是很容易让人一听就懂的概念。“一个类可以被多个线程安全调用就是线程安全的”《Java编程并发实践》。

        来说说静态变量、实例变量、局部变量在多线程下的安全问题吧!

    (一)静态变量:线程非安全

       1、静态变量:使用static关键字定义的变量。static可以修饰变量和方法,也有static静态代码块。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

        用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它的类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。

        2、静态变量使用的场景:

        (1)对象间共享值时

        (2)方便访问变量时

        3、静态方法使用注意事项:

        (1)不能在静态方法内使用非静态变量,即不能直接访问所属类的实例变量;

        (2)不能在静态方法内直接调用非静态方法;

        (3)静态方法中不能使用this和super关键字;

        4、验证静态变量的线程安全性:

        (1)从程序执行的图中我们可以看出,执行结果中有错误数据,证明了静态变量是存在资源冲突问题的。

        (2)程序运行结果图: 

        wKioL1XIYiCz51UGABceSj2NUtI169.bmp

        5、结论:静态变量也称为类变量,属于类对象所有,位于方法区,为所有对象共享,共享一份内存,一旦值被修改,则其他对象均对修改可见,故线程非安全。

    (二)实例变量:单例时线程非安全,非单例时线程安全

        1、实例变量:实例变量属于类对象的,也就是说,属于对象实例私有,在虚拟机的堆中分配。

        2、验证实例变量的线程安全性:

        (1)从程序截图中,我们可以看到,当为单例模式时,会产生资源冲突,当非单例模式时,则不会产生线程冲突。

        (2)程序运行结果图:

        图1:

        wKioL1XIYl_RoatmABZU8hrY9Ck087.bmp

        图2:

        wKioL1XIYpzTOhE2ABZK5iG2N3I856.bmp

     3、结论:实例变量是实例对象私有的,系统只存在一个实例对象,则在多线程环境下,如果值改变后,则其它对象均可见,故线程非安全;如果每个线程都在不同的实例对象中执行,则对象与对象间的修改互不影响,故线程安全。

    (三)局部变量:线程安全

         1、局部变量:定义在方法内部的变量。

         2、验证局部变量的安全性:

        (1)从程序截图中可以看出,局部变量在多线程下没有产生资源冲突的问题

        (2)程序运行结果图:

        wKiom1XIYLvxqpwpABZORsRL6uY028.bmp

        3、结论:每个线程执行时都会把局部变量放在各自的帧栈的内存空间中,线程间不共享,故不存在线程安全问题。

    (四)静态方法的线程安全性

         1、静态方法中如果没有使用静态变量,则没有线程安全的问题;

              静态方法内的变量,每个线程调用时,都会新创建一份,不会公用一个存储单元,故不存在线程冲突的问题。

        以上就是对多线程环境下静态变量、实例变量和局部变量的一点点研究,也仅供自己在需要或遗忘的时候查询参考下了。

    总的来说安全问题:局部变量>成员变量>全局变量

  • 相关阅读:
    jqueryautocomplete
    了解CSS的查找匹配原理 让CSS更简洁、高效
    html5网页编码
    刚开始学习 mvc碰到的郁闷问题
    datatable 批量插入方法 求解?
    28个经过重新设计的著名博客案例(1120)
    递归调用中的return
    C++新建一个模板
    C++ 中用 sizeof 判断数组长度
    为什么MySQL选择REPEATABLE READ作为默认隔离级别?
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13724705.html
Copyright © 2020-2023  润新知