前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在Java中什么时候才要考虑线程安全

在Java中什么时候才要考虑线程安全

作者头像
AlbertYang
发布2020-09-08 14:58:05
1.3K0
发布2020-09-08 14:58:05
举报

★什么是线程安全?★

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

举一个例子:小明和小红同时访问同一个方法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修饰符

代码语言:javascript
复制
public void synchronized M(){
     // TODO
}

使用synchronized修饰的方法,就叫做同步方法,保证线程执行该方法的时候,其他线程只能在方法外等着,等该线程执行完成后其他线程才能继续执行这个方法。

2、同步代码块

代码语言:javascript
复制
synchronized(同步锁对象)
{
     // 需要同步操作的代码
}

对象的同步锁可以想象是在对象上标记了一个锁,而且对应了一个唯一的钥匙,谁拿到锁的钥匙,谁就可以进入代码块,其他线程只能在代码块外面等着,在任何时候,Java虚拟机最多允许一个线程拥有该对象的同步锁。

Java程序运行时可以使用任何对象作为同步监听对象,但是一般的,我们把当前并发访问的共享资源和变量作为同步监听对象。

实际上,同步方法和同步代码在本质上是一样的,两者都用了一个关键字synchronized,synchronized保证了多线程并发访问时的同步操作,避免线程的安全性问题,但是有一个弊端,使用synchronized的方法或代码块,性能会比不用时要低一些,因此如果要用synchronized,应该尽量减小synchronized的作用域。

ALbertYang

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AlbertYang 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档