什么是线程安全,解决线程安全的方法

什么是线程安全,解决线程安全的方法 前言来自我对一位我所崇拜的大佬文章的评论:我:“喝罢黄河之水天上来,酒醒杨柳残月且偷欢,唱罢笑傲江湖祭沧海,雁渡寒潭有几只回还”大佬:“年少正恰,纵码飞骋,略江山华月,有几人随傅虎

前言

来自我对一位我所崇拜的大佬文章的评论:

我:“喝罢黄河之水天上来,酒醒杨柳残月且偷欢,唱罢笑傲江湖祭沧海,雁渡寒潭有几只回还”

大佬:“年少正恰,纵码飞骋,略江山华月,有几人随傅虎踞龙盘。”


进入正题

线程或者锁在并发编程中的作用,类似于铆钉和工字梁在土木工程中的作用。要建筑一座坚固的桥梁,必须正确地使用大量的铆钉和工字梁。同理,在构建稳健的并发程序时,必须正确地使用线程和锁。但这些终归只是一些机制。要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享(Shared)和可变的(Mutable)状态的访问。

  • 对象的状态:指存储在状态变量中的数据,当然也可能包含其他依赖对象的域。 例如,某个 HashMap 的状态不仅存储在 HashMap 对象本身,还存储在许多 Map.Entry 对象中。在对象的状态中包含了任何可能影响其外部可见行为的数据。
  • 共享Shared:共享意味着变量可以有多个线程同时访问。
  • 可变Mutable:意味着变量的值在其生命周期内可以发生变化。

注释:讨论线程安全性,更应该侧重于如何防止在数据上发生不受控的并发访问。一个对象是否需要是线程安全的,取决于他是否被多个线程访问。(指的是在程序中访问对象的方式,而不是对象要实现的功能)

当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。

  • 关键字 synchronized:提供独占的加锁方式。
  • voatile 类型变量:同步应该要包括的还有,显式锁(Explicit Lock)以及原子变量。

如果忽略了某一个同步的机制,可能会造成的后果,当多个线程访问同一个可变的状态变量时没有使用合适的同步,程序就会出错,修复:

  • 不在线程之间共享该状态变量
  • 将状态变量修改为不可变的变量
  • 在访问状态变量时使用同步

注释:当设计线程安全的类时,良好的面向对象技术、不可修改性,以及明晰的不变形规范都能起到一定的帮助作用。

在编写并发应用程序时,一种正确的编程方法就是:首先代码正确运行,然后再提高代码速度。即便如此,最好也只是当性能测试结果和应用需求告诉你必须提高性能,以及测量结果表明这种优化在实际环境中确实能带来性能提升时,才进行优化。


什么是线程安全性

我们都知道:定义越正式,就越复杂,不仅很难提供由实际意义的指导建议,而且也很难从直观上去理解。网上的“定义”有很多,比如:

  • ······ 可以在多个线程中调用,并且在线程之间不会出现错误的交互。
  • ······ 可以同时被多个线程调用,而调用者无须执行额外的动作。

也难怪我们会对线程安全性感到困惑,因为听起来就想“如果某个类可以在多个线程中安全的使用,那么它就是一个线程安全的类。”虽然不存在很多争议,但是有什么实际的意义和帮助么。

“安全”的含义是什么:

  • 在线程安全的定义中,最核心的概念就是正确性。
  • 正确的含义是——某个类的行为与其规范完全一致

我将单线程的正确性近似定义为“所见即所知”,在对“正确性”给出了一个较为清晰的定以后,就可以定义线程安全性:

  • 当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。
  • 当多个线程访问某个类时,不关于刑事环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称呼这个类是线程安全的。
  • 由于单线程程序也可以看成多线程程序,若某个类在单线程环境下都不是正确的,那么它肯定不会是线程安全(也就是说一个程序首先要能正常的工作保证正确性)。

简单的示例

通常,线程安全性的需求并非来源于对县城的直接使用,而是使用像 Servlet 这样的框架(还有很多)。

一个基于 Servlet 的因数分解服务,并逐步扩展功能,并确保它的线程安全性。

一个无状态的 Servlet:

@ThreadSafe
public class StatelessFactorizer implements Servlet {
	public void service(ServletRequest req,ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
        encodeIntoResponse(resp,factors);
	}
}

与大多数 Servlet 相同,StatelessFactorizer 是无状态的,它既不包含任何域,也不包含任何对其他类中域的引用。计算过程中的临时状态仅存在于线程栈上的局部变量中,并且只能由正在执行的线程访问。访问 StatelessFactorizer 的线程不会影响另外一个访问同一个 StatelessFactorizer 的线程的计算结果 ,因为这两个线程并没有共享状态,就好像他们都在访问不同的实例。由于线程访问无状态对象的行为并不会影响其他线程中操作的正确性,因此无状态对象是线程安全的。

  • 无状态对象一定是线程安全的。
  • 大多数 Servlet 都是无状态的,从而极大地降低了在实现 Servlet 线程安全性时的复杂性。只有当 Servlet 在处理请求时需要保存一些信息线程安全性才会成为一个问题。

作者:Sunny_Chen链接:https://juejin.cn/post/6999423430462275592

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/86994.html

(0)

相关推荐

  • 满口种植牙需要多少钱?,种植满口牙,大约24颗总价大约需要多少钱

    种牙满口多少钱(最新2021)网友提问:种牙满口多少钱(最新2021)优质回答:我们在经历了龋齿、牙周炎等各种牙病后,最终难逃牙齿掉落的命运。国家卫计委最新发布的《全国第四次口腔健康流行病学调查结果》显示:我国35~44

    攻略 2021年11月19日
  • 糯米切糕(糯米面年糕)

    社区糯米切糕(糯米面年糕)将糯米淘洗干净,当模具用的饭盒子做法糯米洗净,放入木桶内,取出放入盆中,、上面放点红塘最后就是蒸煮啦,逢年过节很多地方都有吃年糕的习俗.揉成块状,糯稻谷加工成的大米。
    或者也可以蘸芝麻糖蓉,用凉

    电商 2021年11月16日
  • 不需要从业资格证,职业资格证书可以上岗用吗

    来源:中国质量新闻网近日,在依据《关于开展技术技能类“山寨证书”专项治理工作的通知》开展专项治理时,

    2022年5月28日
  • 饮水机没有水了会烧坏吗,饮水机里面没水会不会烧起来

    饮水机没水了会烧坏吗饮水机空着也不会烧坏。前提是饮水机内胆还有一些水。如果长时间不放水,会烧坏,甚至引起火灾爆炸,非常危险。建议饮水机断水时及时换水,以免影响饮水机的正常使用。当饮水机的桶里没有水时,就需要更换一桶纯净水

    电商 2021年10月29日
  • 甜蜜相机怎么上传本地音乐? 甜甜的摄像头会上传本地音乐吗

    一甜相机怎么上传本地音乐 一甜相机上传本地音乐方法,甜甜的摄像头怎么上传音乐? 介绍上传当地音乐的方法。 1、打开甜蜜摄像头,选择视频,点击音乐, 2、选择我的,点击从视频中提取音...

    阅读 2022年10月23日
  • 樱花动漫app安卓下载最新版本,樱花动漫app

    樱花动漫app,樱花动漫app下载苹果版最新樱花动漫app是一款结合了动画和漫画的阅读软件。而漫画、动漫平台都有正版资源。推荐国民友谊板块。支持郭曼,女神的女神已经到了。同时,日漫也是一股强大的新生力量。满足用户的阅读需求。樱花令每个人着迷。花絮虽已落地,但随风起舞的美好早已不自觉地记在心里。樱花动漫app下载苹果版最新特色1、多种阅读模式,横屏竖屏自由切换,可用多种手势操作。2、独特的图片处理技术,节省更多手机空间,带给你别具一格的阅读体验。3、为网络不稳定的情况配备自动缓存功能,看漫画更放心。樱花动漫app下载苹果版最新亮点动态漫视频:原创,独家,超萌动画大放送。神漫:神界传说,极品漫画,

    2022年11月7日