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

举报
AlbertYang 发表于 2021/02/03 00:29:46 2021/02/03
【摘要】 点击蓝字关注我们 本文字数:978字 阅读时间:3分钟 ★什么是线程安全?★ 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行...

640?wx_fmt=gif

点击蓝字关注我们

640?wx_fmt=gif

640?wx_fmt=png

本文字数:978字

阅读时间:3分钟

640?wx_fmt=png

★什么是线程安全?★

xmorient

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

举一个例子:小明和小红同时访问同一个方法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中什么时候考虑线程安全?★

640?wx_fmt=gif

单线程的时候我们无需考虑线程安全,这个不用多说,对于局部变量,每个线程执行时都会把局部变量放在各自栈帧的工作内存中,线程间不共享,故也不需要考虑线程安全问题。Java中有以下两种变量需要考虑线程安全问题:

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

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

AlbertYang

★如何解决线程安全问题?★

640?wx_fmt=gif

Java中主要通过以下两种方式解决线程安全问题:

1、同步方法

给多线程访问的成员方法加上synchronized修饰符


   
  1. public void synchronized M(){
  2. // TODO
  3. }

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

2、同步代码块


   
  1. synchronized(同步锁对象)
  2. {
  3. // 需要同步操作的代码
  4. }

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

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

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

ALbertYang

你“在看”我吗?

640?wx_fmt=png

文章来源: albertyang.blog.csdn.net,作者:Albert Yang,版权归原作者所有,如需转载,请联系作者。

原文链接:albertyang.blog.csdn.net/article/details/96472634

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。