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

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

  1. Java.util.concurrent.atomic包,其中包含了大量使用到Unsafe这个类
  2. Java不能直接访问操作系统的底层,而是通过本地方法来访问。

Unsafe类提供了硬件级别的原子操作,主要提供了以下功能

  • 内存操作
  • 字段的定位和修改
  • 挂起和恢复
  • CAS操作(乐观锁)

内存操作

  • 类提供的3个本地方法allocateMemory、reallocteMemory、freeMemory分别用于分配内存、扩充内存和释放内存
//和C语言的3个方法对应/**分配内存**/
public native long allocateMemory(long 1);/**扩充内存**/
public native long reallocateMemory(long 1,long l1);/**释放内存**/
public native void freeMemory(long 1);

字段的定位和修改

  • 可以定位对象字段的内存位置,也可以修改对象的字段值,即使它是私有的

挂起和恢复

  • 将一个线程鼓起是通过park实现的,调用park后,线程会一直阻塞直到超时或者中断等条件的出现
  • unpark可以终止一个挂起的线程,使其恢复正常
  • 整个并发框架中对于线程的挂起操作被封装在LockSupport类中,LockSupport类中有各种版本的pack方法,但是最终都调用了Unsafe.park()方法

CAS操作(乐观锁)

  • CAS(Compare And Swap)比价并交换
  • CAS操作包含三个操作数    内存位置(V)、预期位置(A)、新值(B)
  • 如果内存位置和预期的原值相匹配,那么处理器就会自动将该位置更新为新值。否则,处理器不做任何操作。无论那种情况,它都会在CAS指令之前返回该位置的值
  • 简单讲就是,我认为V应该包含A值,如果复合预期,就将B放到这个位置,否则,不要改变该位置,只告诉我这个位置现在的值就可以
  • Java并发包(java.util.concurrent)中大量使用了CAS操作,涉及到并发的地方都调用了sun.misc.Unsafe类方法进行CAS操作,在Unsafe中是通过compareAndSwapXXX方法实现的。

底层方法如下

/*
*比较obj的offset处内存位置中的值和期望的值,如果相同则更新,此更新是不可中断的*@Param obj需要更新的操作
*@Param offset obj中整型的field偏移量
*@Param expect 希望field中存在的值
*@Param update 如果期望值except与field当前值相同,设置field这个值为新值
*@return 如果field的值将被改变则返回true
*/
public native boolean compareAndSwapInt(Object obj,long offset,int expect,int update)

CountDownLatch

  • CountDownLatch:用于监听某些初始化操作,并且将线程进行阻塞,等初始化执行完毕之后,通知主线程继续工作执行

CyclicBarrier

  • CyclicBarrier:栅栏的概念,多线程的进行阻塞,等待某一个临界值条件满足后,同时执行
  • 比如:将每一个线程比作一个跑步运动员,只有所有的运动员都准备好,才能一起赛跑,只要一个人没有准备好,大家都等等待

Future与Caller回调

  • Future模式:这种模式主要是利用空间换取时间的概念,也就是异步执行(需要开启一个新的线程)
  • Future模式非常适合在处理耗时很长的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量

利用设计模式模拟Future

  • Future模式有点类似于商品订单
  • 比如网购的时候,挑选商品,提交订单,付款即可。当订单处理完成之后,在家里等待商品送货上门即可。或者形象的说,当我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无需一直等待请求的结果,可以继续浏览或者操作其他内容

Exchanger多线程间数据交换

  • Exchanger用于进行线程间的数据交换,它提供了一个同步点,在这个同步点,两个线程可以交换彼此的数据
  • 两个线程通过exchange方法交换数据,如果一个线程先执行excange方法,它会一直等待第二个线程也执行exchange方法
  • 当两个线程都达到同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方
  • 使用的场景:1,遗传算法:遗传算法里需要选两个人作为交换对象,这时会交换两人的数据,并使用交叉规则得出两个人的交换结果;2,文字校对:A和B同时录入数据,然后对A和B进行比较,看是否录入一致,保证数据录入的正确性;

ForkJoin并行框架

  • Frok/Join框架是Java提供的一个用于并行执行任务的框架,将一个大任务分割成若干个小任务,最终汇总每一个小任务的结果后从而得到大任务的结果
  • ForkJoinTask:使用该框架,需要创建一个ForkJoin任务,它提供在任务中执行fork和join操作的机制。一般情况下,我们不需要直接继承ForkJoinTask类,只需要继承他的子类即可
  • RecursiveAction:用于没有返回结果的任务
  • RecursiveTask:用于有返回结果的任务
  • ForkJoinPool:任务ForkJoinTask需要通过ForkJoinPool来执行

Master-Worker并发组件设计模式

  • Master-Worker模式是常用的并发计算模式,他的核心思想是系统由两类进程协作工作:Master和aworker进程
  • Master进程负责接收和分配任务,Worker进程负责处理子任务。当各个Worker子进程处理完成之后,会将结果返回给Master,由Master做归纳和总结
  • 其好处是将一个大任务分解成若干个小任务,并行执行,从而提高系统的吞吐量
  • Master-Worker并发组件设计模拟

Semaphore信号量与限流策略

  • Semaphore信号量非常适合并发访问限制,用于对系统的访问量进行评估。投入资源太大,资源利用率达不到实际效果,纯粹浪费资源;投入资源太小的话,如果一个高峰值的访问量会压垮系统

Semaphore相关概念

  • PV(page view)网站的总访问量,页面浏览量或者点击量,用户每刷新一次就会记录一次
  • UV(unique Visitor)访问网站的一台电脑客户端为一个访客。一般来讲时间上00:00~24:00之内相同ip的客户端记录
  • QPS(query per second)即每秒查询数,qps很大程度上代表了系统业务上的繁忙程度,每次请求的背后,可能对应着多次磁盘I/O,多次网络请求,多个cpu时间片等。通过qps可以非常直观了解当前系统业务情况,一旦当前qps超过所设定的预警阀值,可以考虑增加机器对于集群的扩容,防止压力太大导致宕机,可以根据前期的压力测试,在结合后期压力测试得到估值,再结合后期综合运维情况,估算出阀值
  • RT(response time)请求的响应时间,这个指标非常关键,直接说明前段用户的体验
  • 当然还涉及cpu、内存、网络、磁盘等情况,更细节的问题很多,如select、update、delete/ps等数据库层面的统计。
  • 容量评估:一般来说通过开发、运维、测试、以及业务等相关人员,综合出系统的一系列阀值,然后我们根据关键阀值如qps、rt等,对系统进行有效的变更。
  • 一般来讲,我们进行多轮压力测试以后,可以对系统进行峰值评估,采用所谓的80/20原则,即80%的访问请求将在20%的时间内达到。这样我们可以根据系统对应的PV计算出峰值qps。
  • 峰值qps= (总PV × 80%)/ (60 × 60 × 24 × 20%)
  • 然后在将总的峰值qps除以单台机器所能承受的最高的qps值,就是所需要机器的数量:机器数 = 总的峰值qps / 压测得出的单机极限qps
  • 当然不排除系统在上线前进行大型促销活动,或者双十一、双十二热点事件、遭受到DDos攻击等情况,系统的开发和运维人员急需要了解当前系统运行的状态和负载情况,一般都会有后台系统去维护。    

 

 

 

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

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

相关文章

写软件不是造汽车

写软件和做其他事情是不一样的。当我们制造别的东西的时候——像汽车、玩具、椅子、画作、甚至包括数字产品如平面图片和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…

用Unix的设计思想来应对多变的需求

摘要:无论是Unix设计,还是面向对象设计,还是别的什么如SOA,ECB,消息,事件,MVC,网络七层模型,数据库设计,等等,他们都在干三件事——解耦&#xff…