Java多线程中static变量的使用

Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果?
Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果?仅仅是多耗资源还是会引发异常?

不会耗资源 也不会引发异常
而是程序出现逻辑错误,如本来该出现 3 的地方出现了 2 …,这比前两种情况更严重

Java多线程中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)程序运行结果图:

img

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

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

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

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

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

(2)程序运行结果图:

图1:

img

图2:

img

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

则对象与对象间的修改互不影响,故线程安全。

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

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

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

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

(2)程序运行结果图:

img

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

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

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

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

总结:

  1. java在执行静态方法时,会在内存中拷贝一份,如果静态方法所在的类里面没有静态的变量,那么线程访问就是安全的,比如在javaee中服务器必然会多线程的处理请求此时如果设计全局需要调用的静态方法,可用此种设计。

  2. java在执行静态方法时,如果使用静态变量,同时类的函数设计时使用到了静态数据,最好在调用函数时使用synchronized关键字,否则会导致数据的不一致行。

  3. 加静态全局的变量,在多线程访问下定会出现数据的不一致行,最好使用synchronized关键字,确保数据的一致性,典型的代表就是单例模式。

  4. java是线程安全的,即对任何方法(包括静态方法)都可以不考虑线程冲突,但有一个前提,就是不能存在全局变量。如果存在全局变量,则需要使用同步机制。

加入synchronized关键字的静态方法称为同步静态方法。
在访问同步静态方法时,会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。这个其实就是操作系统中的用信号量实现进程的互斥与同步问题,如果涉及在同一个类中有多个静态方法中处理多线程共享数据的话,那就变成用信号量解决生产者-消费者问题。也就是说,静态方法是一份临界资源,对静态方法的访问属于进入临界区;对静态变量的修改是一份临界资源,对静态变量的修改属于进入临界区。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scanf 接收 空格 输入_如何允许使用scanf输入空格?

人们(尤其是初学者)不应该使用scanf(“%s”)或gets()或任何其他没有缓冲区溢出保护的函数,除非你确定输入总是一个特定的格式甚至不是)。记住,scanf代表“扫描格式化”,并且珍贵的格式比用户输入的数据少。如果您对输入数据格式具…

Java并发——线程安全

1、线程安全 多个线程对同一个共享变量进行读写操作时可能产生不可预见的结果,这就是线程安全问题。 故线程安全的核心点就是共享变量,只有在共享变量的情况下才会有线程安全问题。这里说的共享变量,是指多个线程都能访问的变量&#xff0c…

vue 功能模块后台可配置_Github14k的Springboot后台管理系统

关注爱编码、挖掘优秀项目。本期给各位带来的一款优质的后台管理系统:EL-ADMIN 后台管理系统。简介该项目由大神elunez一手大打造。它是一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统。项目地址&am…

hibernate mysql 时间_使用Hibernate和MySQL创建时间戳和最后更新时间戳

慕斯卡3215842利用本文中的资源以及从不同来源获得的左右信息,我提出了这个优雅的解决方案,创建了以下抽象类import java.util.Date;import javax.persistence.Column;import javax.persistence.MappedSuperclass;import javax.persistence.PrePersist;i…

Java中保证线程安全的三板斧

前言 现在,如果要使用 Java 实现一段线程安全的代码,大致有 synchronized 、 java.util.concurrent 包等手段。虽然大家都会用,但却不一定真正清楚其在 JVM 层面上的实现原理,因此,笔者在查阅了一些资料后&#xff0c…

mysql oa数据库设计_OA项目1:环境搭建之数据库创建与环境添加

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频我的文字版实践笔记,本人用此来加强巩固自己开发知识,如有网友转载,请注明。谢谢。一 指定数据库:Mysqldatabase:oa建库语句:crea…

java 线程安全的原因_java的多线程:java安全问题产生的原因与JMM的关系

一、多线程产生安全问题 1、Java内存模型 共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入时,能对另一个线程可见。 从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系: 线程之间的共享变量存储在主内存…

python用pip安装wordcloud_如何在python3.7中使用pip安装wordcloud

我一直试图在windows10上pip安装python3.7的wordcloud,但我一直收到这个错误消息,我不太理解,也无法修复。在正在为wordcloud运行setup.py安装:已完成,状态为“error”Complete output from command "c:\program …

分布式系统全局唯一ID的几种实现方式

现如今可谓是微服务、分布式、IoT(物联网)横行的时代,作为一名开发者始终还是要保持一定的危机意识,特别是在日常的项目开发中,若是有机会接触到一些关于微服务、分布式下的应用场景,应当硬着头皮、排除万难…

git如何查看缓存区文件内容_详解Git工作区、暂存区、历史记录区以及git reset、git revert、git checkout等撤销命令的区别...

一、可以将git简单的分为三个区域 1、工作区(working directory) 2、暂缓区(stage index) 3、历史记录区(history) 如图:其中git add files 把当前工作目录中的文件放入暂存区域这其实做了两件事: 1、将本地文件的时间戳、长度&#xff0…

分布式全局唯一ID的实现

分布式全局唯一ID的实现 前言 上周末考完试,这周正好把工作整理整理,然后也把之前的一些素材,整理一番,也当自己再学习一番。 一方面正好最近看到几篇这方面的文章,另一方面也是正好工作上有所涉及,所以决…

mysql多个分类取n条_MySQL获取所有分类和每个分类的前N条记录

MySQL获取所有分类和每个分类的前N条记录。比如有文章表 test(Id,type,tiem),现在要用SQL找出每种类型中时间最新的前N个数据组成的集合,一段不错的代码,留存备用。SELECT a1.* FROM test a1INNER JOIN (SELECT a.type,p.time FROM test aLEF…

Java接口学习(接口的使用、简单工厂、代理模式、接口和抽象类的区别)

前言引入 官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能&#xff0…

java 矩阵转置_图解利用Java实现数组转置

我们编写Java代码,如下图所示:package com.tina;public class demo {public static void main(String args[]) {int data[] new int[] { 1, 6, 3, 9, 5, 7, 2, 0, 4, 8 };PrintArray(data);}// 输出数组内容public static void PrintArray(int arr[]) {…

java中static、final、static final浅析

final final可以修饰类、属性、方法、局部变量、参数,不能修饰接口!final修饰类:该类不能被继承(解释了为什么不能修饰接口,不过接口里面的属性、方法等是可以用final修饰的);final修饰属性&am…

最短路径 floyd java_java实现Floyd算法求最短路径

关于无向图的最短路径问题:这个程序输出:最短路径矩阵例如:W[0][5]9 代表vo->v5的最短路径为9W:0 1 3 7 4 91 0 2 6 3 83 2 0 4 1 67 6 4 0 3 24 3 1 3 0 59 8 6 2 5 0package com.xh.Floyd;import java.util.ArrayList;public class Floyd_01 {publi…

SpringBoot 使用 log4j2

一、新建工程 选择一些基础依赖 填写工程名称和项目路径 二、工程配置 修改文件编码格式 设置Java Compiler 修改maven配置文件路径 三、pom.xml的web依赖中排除掉logging依赖&#xff0c;并且引入log4j2依赖 <dependency><groupId>org.springframework.…

springBoot 通过使用log4j2

1.排除 Spring-boot-starter 默认的日志配置 将原本的 spring-boot-starter 改为 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>…

java finalize 何时被调用_finalize()方法什么时候被调用?析构函数(final

finalize()方法也叫收尾方法。一旦垃圾回收器准备好释放对象占用的存储空间&#xff0c;首先会去调用finalize()方法①进行一些必要的清理工作(对垃圾回收器不能处理的特殊情况进行处理)(例子在下边)②也有可能使该对象重新被引用&#xff0c;我习惯叫这种作用为复活。注意&…

编程和java是什么关系_C语言和Java编程有什么区别?

C语言和Java编程有什么区别&#xff1f;Java从根本上说是c之后的一种改进语言&#xff0c;纯面向对象的一种编程语言(当然比起Ruby还是差一点)&#xff0c;有了C语言的基础固然对学习Java有帮助&#xff0c;因为在某种程度上Java和C语言是比较接近的。但是如果没有学习过C语言也…