线程安全和对应的核心概念

线程安全

  • 线程安全的概念:当多个线程访问某一个类(对象和方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或者方法)就是线程安全的
  • synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为‘互斥区’或者“临界区”
  • 当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排队是按照CPU分配的先后顺序而定的),一个线程想要实现synchronized装饰的方法里的代码,首先是尝试获取锁,如果可以得到锁,就可以执行synchronized代码体的内容;如果拿不到锁,这个线程就会不断尝试去获取锁资源,直到拿到为止;而且是多个线程同时去竞争这把锁(锁竞争)

Synchronized

  • 同步Synchronized:同步的概念就是共享,如果不是共享的资源就没有必要进行同步
  • 异步asynchronized:异步的概念就是独立,相互之间不受到任何制约
  • 同步的目的是为了保证线程的安全,对于线程安全需要保证两个特性 原子性(同步)和可见性

线程之间通信

  • 线程通信的概念:线程是操作系统中独立的个体,但是这些个体如果不经过特殊的处理就不能成为一个整体,线程之间的通信就成为整体的必用的方式之一。当线程之间存在通信指挥,系统之间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对于线程任务在处理过程中,进行有效的把控和监督
  • 使用wait/notify方法实现线程之间的通信(这两个方法都是object的类的方法,即java为所有的对象都提供了这两个方法)
  • wait和notify必须配合synchronized关键字使用
  • wait方法释放锁/notify方法不释放锁

ThreadLocal概念

  • 线程局部变量,是一种多线程间并发访问变量的解决方案,与synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用以空间换时间的手段,为每个线程提供变量的独立副本,以保障线程的安全
  • 从性能上说,ThreadLocal不具有绝对的优势,在并发不是很高的情况下,加锁的性能可能会更好,但是作为一套与锁完全无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用ThreadLocal可以在一定程度上减少锁竞争

Volatile关键字核心概念与应用

  • Volatile:主要作用是使变量在多个线程之间可见
  • 阻止指令的重排序,happens-before
  • 一个线程可以执行的操作有使用(use)、赋值(assign)、转载(load)、存储(store)、锁定(lock)、解锁(unlock)
  • 主内存可以执行的操作有读(read)、写(write)、锁定(lock)、解锁(unlock),每个操作都是原子的
  • volatile的作用就是强制线程到主内存(共享内存)里去读取变量,而不是去线程工作内存里去读取,从而实现了多个线程之间变量的可见,也就是满足线程安全的可见行

JVM

  • Java Memory Model(Java内存模型),简称JVM,用于解决线程对于共享变量的写入何时对于另一个线程可见
  • 所有变量都存储在主内存中,每一个线程都有一个私有的本地内存,本地内存是将该线程使用到的变量,从主内存中拷贝到本地
  • 线程对于变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量也不例外)
  • happens-before规则,例如操作A :i=1;操作B:j=i;如果操作Ahappens-before操作B,那么操作B完成之后,j的值一定为1;
  • 因为happens-before关系可以向程序员保证,在操作B执行之前,操作A的执行后的影响【或者说明结果】(修改i的值)对于操作B是可以观察到的【可见的】

规则

  • 简而言之,使用happens-before概念来阐述操作之间的内存可见行
  • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作,也就是说,你写的操作,如果是单线程执行,那么前面的操作就会happens-before于后面的操作
  • 监视器锁规则:对于一个锁的解锁,happens-before于随后对这个锁的加锁
  • Volatile变量规则:对于一个volatile域的写,happens-before于任意后续对这个volatile域的读
  • 传递性规则:A happens-before B,B happens-before C,则A happens-before C

指令重排序

  • 为了保证程序的最终运行结果需要和在单线程严格意义的顺序化环境下执行的结果一致,程序指令的执行顺序有可能和代码的顺序不一致,这个过程就称之为指令的重排序
  • 指令的重排序的意义:JVM利用处理器的特性,充分利用多级缓存,多核等进行适当的指令重排序,从而可以充分利用CPU的执行特点,最大程度上发挥机器的性能

Atomic系列类比

  • Atomic系列类封装了一系列的基础类型和对象操作,其目的是为了实现原子性
  • AtomicInteger
  • AtomicLong
  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReference
  • 注意:在对Atomic类操作的时候,如果有多个操作执行,那么就是非原子性的,需要加aynchronized进行修饰,保证Atomic类操作的整体原子性

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

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

相关文章

JDK Unsafe类的使用与CAS原子特性

JDK Unsafe类的使用与CAS原子特性 Java.util.concurrent.atomic包,其中包含了大量使用到Unsafe这个类Java不能直接访问操作系统的底层,而是通过本地方法来访问。 Unsafe类提供了硬件级别的原子操作,主要提供了以下功能 内存操作字段的定位和…

写软件不是造汽车

写软件和做其他事情是不一样的。当我们制造别的东西的时候——像汽车、玩具、椅子、画作、甚至包括数字产品如平面图片和3D模型——我们做出来的成品就是最终的结果。而开发软件则不是,我们做出来的产品永远不可能有最终的结果——我们需要向计算机解释如何根据任意…

线程池核心概述

线程池核心概述 Executors工厂类使用 Executors工厂类底层源码分析详解 ThreadPoolExecutor自定义线程池 ThreadPoolExecutor拒绝策略详解 计算机密集型与IO密集型详解 如何正确的使用线程池…

网站盈利的10种方式

如果你有自己的网站,而且已经有了不少的流量,你肯定会开始考虑如何通过这个网站来挣一些钱。 在这篇文章中,我会向大家介绍网站最常见的10种盈利方式。 1.按点击付费广告 在网站上展示一个按点击付费的广告横幅是最简单的盈利方式&#xff…

程序员如何创业?

摘要:工作机会减少,读大学也不是保障。大公司亦不再是构筑职业生涯的安全港湾。透过媒体的镜头,创业似乎成了沙漠中唯一的绿洲。然而关于创业,或许少有人给你建议,这里所列出的一些因素都是你可以考虑的。 如果你的年…

Redis数据的类型

Redis一共分为五种基本数据类型:String、Hash、List、Set、Zset. string 内部编码有三种,raw,embstr,int String 是二进制的。可以存储序列化对象,图片,字符串,数值等 set和get方法 &#x…

Redis高级命令与特性以及单点模式的介绍

高级命令 keys * 返回满足条件的所有key,可以模糊匹配exists 是否存在指定的keypersist 取消过期时间select 选择数据库 (0-15,总共16个数据库)move key index 将当前数据库的 key 移动到给定的数据库 db 当中randomkey 随机返回…

华为副总裁徐家骏离职:年薪千万工作感悟十二条

从普通的公司职员,到年薪千万的华为副总裁,再到离开华为转战百度,徐家骏的十年从业经历和经验可资借鉴,我们从中也可以一窥华为的运作过程。徐家骏是华为数据中心的头,技术超级牛人,一级部门总监&#xff0…

Redis持久化之RDB和AOF

Redis持久化之RDB和AOF Redis 有两种持久化方案,RDB (Redis DataBase)和 AOF (Append Only File); RDB 详解 RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作&#…

同为程序员 为什么我的工资最低

我看着工资单上每一个开发团队成员的薪水,慢慢地我不能保持淡定了。 而当我看到我的工资排名是倒数的时候——靠近最后一名——我不由得倒抽一口冷气。就像圣诞故事中的那个可爱的小男孩Ralphie ,想买气枪却被忽悠会有危险一样,我也不断忽悠…

Docker安装Redis以及配置Redis环境

1,下载Redis镜像 首先拉取 Redis 镜像, 这里我选择的是 redis:alpine 轻量级镜像版本 docker pull redis:alpine 下载完成后,通过 docker images 查看我们已经下载的镜像,看看是否已经下载到本地 2,运行 Redis 容器 docker run …

.NET程序性能的基本要领

摘要:本文分享了性能优化的一些建议和思考,比如不要过早优化、好工具很重要、性能的关键,在于内存分配等。开发者不要盲目的没有根据的优化,首先定位和查找到造成产生性能问题的原因点最重要。 【编者按】Bill Chiles&#xff08…

redis.conf配置文件详解

基本配置 daemonize no #是否以后台进程启动databases 16 #创建database的数量(默认选中的是database 0)save 900 1 #刷新快照到硬盘中,必须满足两者要求才会触发,即900秒之后至少1个关键字发生变化save 300 10 #必须是300秒之后至少10个关键字发生变…

什么原因成就了一位优秀的程序员?

这些年我曾和很多程序员一起工作,他们之中的一些人非常厉害,而另一些人显得平庸。不久前因为和一些技术非常熟练的程序员工作感觉很愉快,我花了一些时间在考虑我佩服他们什么呢?什么原因让优秀的程序员那么优秀,糟糕的…

Redis的哨兵模式Sentinel

sentinel功能 redis的sentinel系统用于管理多个redis服务器,该系统主要执行三个任务:监控、提醒、自动故障转移。 1、监控(Monitoring): Redis Sentinel实时监控主服务器和从服务器运行状态,并且实现自动…

csdn 到底怎么了?不准转载?

我转载了20多文章,很多人阅读过,但是今天看到阅读量是0, csdn 到底怎么了? 对用户这样?请大家看看是不是这样?

python3之后版本读取网页的内容

import urllib.request url "http://helloworldbook2.com/data/message.txt" #直接通过url来获取网页数据 print(第一种) response urllib.request.urlopen(url) code response.getcode() html response.read() mystr html.decode("utf8") response.c…

三十功名尘与土——资深程序员生涯自白

摘要:作者Codist(网名)在程序员岗位上工作了三十多年,在这期间他悟出了一些真理,比如,成功来自对失败的总结学习;条条大路通罗马,罗马并不在乎你用什么方式到达。你在生活中积累了哪…

linux/unix核心设计思想

1) 程序应该小而专一,程序应该尽量的小,且只专注于一件事上,不要开发那些看起来有用但是90%的情况都用不到的特性; 2) 程序不只要考虑性能, 程序的可移植性更重要,shell和perl&…

操作系统环境变量

在 Java中,许多类都是 Iterable ,主要包括所有的 Collection 类(但不包括各种 Maps )。 例如,下面的代码可以显示所有的操作系统环境变量: // collections/EnvironmentVariables.java // {VisuallyInspect…