在Java中什么时候才要考虑线程安全
★什么是线程安全?★
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
举一个例子:小明和小红同时访问同一个方法M(),而且他们在不同的线程中。小明所在的线程称为A线程,小红所在的线程称为B线程,线程A和线程B有一个共享的变量G。小明去访问方法M(),改变G的值为Ga,小红也通过方法M()来改变G的值为Gb,正常情况下,小红应该等小明访问完成时再访问,但当G的值还未变成Ga时,小红就通过M()方法来访问G了,此时G的值为假设为Ga’,本来小红应该在Ga上进行改变,却在Ga’上进行了改变,而且此时小明的线程还未结束,小明得到的也不再是Ga,这样就导致的数据的错误,我们称线程A和B之间是线程不安全的。
AlbertYang
★Java中什么时候考虑线程安全?★
单线程的时候我们无需考虑线程安全,这个不用多说,对于局部变量,每个线程执行时都会把局部变量放在各自栈帧的工作内存中,线程间不共享,故也不需要考虑线程安全问题。Java中有以下两种变量需要考虑线程安全问题:
1. 静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。
2. 实例变量为对象实例私有,在虚拟机的堆中分配,若在系统中只存在一个此对象的实例,在多线程环境下,“犹如”静态变量那样,被某个线程修改后,其他线程对修改均可见,故线程非安全;如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变量的修改将互不影响,故线程安全。
AlbertYang
★如何解决线程安全问题?★
Java中主要通过以下两种方式解决线程安全问题:
1、同步方法
给多线程访问的成员方法加上synchronized修饰符
public void synchronized M(){
// TODO
}
使用synchronized修饰的方法,就叫做同步方法,保证线程执行该方法的时候,其他线程只能在方法外等着,等该线程执行完成后其他线程才能继续执行这个方法。
2、同步代码块
synchronized(同步锁对象)
{
// 需要同步操作的代码
}
对象的同步锁可以想象是在对象上标记了一个锁,而且对应了一个唯一的钥匙,谁拿到锁的钥匙,谁就可以进入代码块,其他线程只能在代码块外面等着,在任何时候,Java虚拟机最多允许一个线程拥有该对象的同步锁。
Java程序运行时可以使用任何对象作为同步监听对象,但是一般的,我们把当前并发访问的共享资源和变量作为同步监听对象。
实际上,同步方法和同步代码在本质上是一样的,两者都用了一个关键字synchronized,synchronized保证了多线程并发访问时的同步操作,避免线程的安全性问题,但是有一个弊端,使用synchronized的方法或代码块,性能会比不用时要低一些,因此如果要用synchronized,应该尽量减小synchronized的作用域。
ALbertYang
- 动态绑定与静态绑定
- Android4.0 声卡配置-高通msm8916移植
- PHP安全:session劫持的防御
- 函数式非凡的抽象能力
- 设备树的interrupt
- gitignore文件的作用
- 《Redis设计与实现》读书笔记(十八) ——Redis客户端属性设计与原理
- 使用Python Pandas处理亿级数据
- PHP函数
- Spray中的Authentication和JMeter测试
- 《Redis设计与实现》读书笔记(二十一) ——Redis服务器定时函数serverCron详解
- Spark SQL访问Postgresql
- sysfs_create_group创建sysfs接口
- apache服务器配置
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Linux下怎么切换使用两个版本的JDK
- Linux下Nginx安装的方法(pcre和openssl)
- Apache设置反向代理的方法
- CentOS7设置定时任务
- linux上安装zookeeper 启动和关闭的教程
- linux中rz上传、sz下载命令详解
- Linux alias命令编写
- 详解linux系统调用原理
- Linux下安装pyenv的方法
- 详解Linux如何生成随机数字和字符串
- linux(ubuntu)用户连续N次输入错误密码进行登陆时自动锁定X分钟
- linux下安装golang的方法
- Linux系统的文件传输方法
- CentOS 6.8 NFS 文件共享设置的方法
- linux如何mount挂载磁盘并设置开机自动mount的实现