![](https://img-blog.csdnimg.cn/20190918140145169.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
04Java多线程高并发
文章平均质量分 53
Java多线程高并发
专注_每天进步一点点
成为健康快乐长寿有价值的人,拥有明亮灵动的眼睛,平静谦和的微笑。
展开
-
025 Java中有了Synchronized作为锁为啥还需要整出个Lock
1、在Synchronized锁“横行”的时代,假设现在需求是非阻塞地获取锁、响应中断地获取锁、超时地获取锁等需求的时候,Synchronized便解决不了,于是Lock便登场了。Lock登场将加锁和解锁的行为交给使用者(也就是程序员),使得使用锁更灵活了。针对一个场景,手把手进行锁获取和释放,先获得锁A,然后再获取锁B,当锁B获得后,释放锁A同时获取锁C,当锁C获得后,再释放B同时获取锁D,以此类推。这种场景下, synchronized关键字就不那么容易实现了,而使用Lock却容易许多。2、Lo原创 2022-03-19 05:55:31 · 584 阅读 · 0 评论 -
024 Java实现LRU(Least recently used,最近最少使用)算法 之 LinkedHashMap
JDK中LinkedHashMap中的源码可以看到LRU算法的影子在构造LinkedHashMap的时候可以选择一个参数`accessOrder`,默认为`false`,map内部会按照插入顺序进行维护。如果手动把它设置为`true`,那么map内部会按照访问顺序进行维护。accessOrder和构造函数的源码如下:public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map&l.原创 2022-03-16 15:30:57 · 420 阅读 · 0 评论 -
023 手写一个缓存需要考虑的问题(用Java的话,又有哪些可以拿来直接用的)
首先,大致要考虑线程安全,锁(重量级锁Synchronized或读写锁),LRU具体可以用HashMap、ConcurrentHashMapHashMap线程不安全,见源码注释:(The <tt>HashMap</tt> * class is roughly equivalent to <tt>Hashtable</tt>, except that it is * unsynchronized and permits nulls.) Co原创 2022-03-16 15:08:53 · 461 阅读 · 0 评论 -
022 队列同步器(AQS)的接口
同步器的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法。 重写同步器指定的方法时,需要使用同步器提供的如下3个方法来访问或修改同步状态。·getState():获取当前同步状态。·setState(int newState):设置当前同步状态。·compareAndSetState(int expect,int update):使用CAS设置当前状态,该方法能够保证状原创 2022-03-14 21:05:46 · 535 阅读 · 0 评论 -
021 队列同步器(AQS,面向锁的实现者)和 锁(面向锁的使用者)
队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作,并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状 态,在抽象方法的实现过程中免不了要对同步状态进行更改,这时就需要使用同步器提供的3 个方法(getState()、setState(int...原创 2022-03-14 20:44:39 · 77 阅读 · 0 评论 -
020 ThreadLocal的内存泄露问题
ThreadLocal的设计本身就是为了能够在当前线程中有属于自己的变量,并不是为了解决并发或者共享变量的问题。1、看Thread.class源码中的两个属性 /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; /*原创 2022-03-11 17:57:02 · 134 阅读 · 0 评论 -
019 Thread.join()的解释(面试题:三个线程按照顺序执行)
如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回。经典面试题:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? public static void main(String[] args) { // 初始化线程t1,由于后续有匿名内部类调用这个对象,需要用final修饰 final Thread t1 = new Thread(new Runnable() {原创 2022-03-11 12:34:24 · 300 阅读 · 0 评论 -
018 Java中的等待/通知机制
等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类 java.lang.Object上等待/通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B 调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的 关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。调.原创 2022-03-11 10:20:26 · 249 阅读 · 0 评论 -
017 对象、监视器、同步队列和执行线程之间的关系
任意一个对象都拥有自己的监视器(也叫“monitor对象”),当这个对象由同步块或者这个对象的同步方法调用时,执行方法的线程必须先获取到该对象的监视器才能进入同步块或者同步方法,而没有获取到监视器(执行该方法)的线程将会被阻塞在同步块和同步方法的入口处,进入BLOCKED状态。下图描述了对象、对象的监视器、同步队列和执行线程之间的关系。从图中可以看到,任意线程对Object(Object由synchronized保护)的访问,首先要获得 Object的监视器。如果获取失败,线程进入同步队列.原创 2022-03-11 09:41:22 · 170 阅读 · 0 评论 -
016 Java线程状态和状态改变
Java线程的状态Java线程状态变迁线程创建之后,调用start()方法开始运行。当线程执行wait()方法之 后,线程进入等待状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状 态,而超时等待状态相当于在等待状态的基础上增加了超时限制,也就是超时时间到达时将 会返回到运行状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到阻塞 状态。线程在执行Runnable的run()方法之后将会进入到终止状态。注意 Java将操作系统中的运行和就绪两个状态合并称为运原创 2022-03-10 18:00:12 · 232 阅读 · 0 评论 -
015 cpu占用太高追查;top; ps -mp PID -o THREAD,tid,time | more; printf “%x” TID; jstack PID |grep TID -A 30
1、输入top命令,实时显示 process 的动态截图如下发现是PID为23958和13772的进程占用CPU太高,但是,怎么定位到具体线程或者代码呢?2、输入 ps -mp PID -o THREAD,tid,time | more 显示线程列表将PID换成23958发现TID(线程ID)是24079的线程占用cpu太高,占用CPU时间快7个多小时了!其中24079是十进制的,将TID为24079转换为16进制格式命令:printf “%x” TID将TID替换成2.原创 2022-03-10 16:40:17 · 983 阅读 · 0 评论 -
014 concurrent包通用化的实现
由于Java的CAS同时具有volatile读和volatile写的内存语义,因此Java线程之间的通信现 在有了下面4种方式。1)A线程写volatile变量,随后B线程读这个volatile变量。2)A线程写volatile变量,随后B线程用CAS更新这个volatile变量。3)A线程用CAS更新一个volatile变量,随后B线程用CAS更新这个volatile变量。4)A线程用CAS更新一个volatile变量,随后B线程读这个volatile变量。Java的CAS会使用现代处理器上原创 2022-03-10 15:06:07 · 294 阅读 · 0 评论 -
013 看看ReentrantLock中volatile的state和CAS
1、ReentrantLock的类图2、公平锁和非公平锁释放时,最后都要写一个volatile变量state。看源码: protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) th原创 2022-03-10 14:50:18 · 186 阅读 · 0 评论 -
012 CAS、Unsafe类、cmpxchg指令加上lock前缀
编译器不会对volatile读与volatile读后面的任意内存操作重排序;编译器不会对volatile写与volatile写前面的任意内存操作重排序。组合这两个条件,意味着为了同时实现volatile读和volatile写的内存语义,编译器不能对CAS与CAS前面和后面的任意内存操作重排序。在常见的intel X86处理器中,CAS是如何同时具有volatile读和volatile写的内存语义的下面是sun.misc.Unsafe类的compareAndSwapInt()方法的源代码。p原创 2022-03-10 14:07:53 · 847 阅读 · 0 评论 -
011 锁的释放和获取的内存语义
1、锁的释放和获取的内存语义(1) 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。(2) 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。2、锁释放与volatile写有相同的内存语义;锁获取与volatile读有相同的内存语义下面对锁释放和锁获取的内存语义做个总结。(1)线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A 对共享变量所做修改的)消息。(2...原创 2022-03-10 12:26:27 · 124 阅读 · 0 评论 -
010 内存屏障、内存屏障的类型、如何实现volatile的“可见性(Lock指令和缓存一致性协议)”和“顺序性(内存屏障,禁止指令重排序)”
1、内存屏障的定义2、内存屏障的类型3、volatile关键字的 “可见性” 就是通过 “内存屏障” 来实现的插入内存屏障来禁止特定类型的处理器重排序,来实现volatile关键字的 “可见性”...原创 2022-03-10 10:41:46 · 188 阅读 · 0 评论 -
009 Java如何实现原子操作以及CAS的三大问题
在Java中可以通过锁和循环CAS的方式来实现原子操作。1、使用锁机制实现原子操作锁机制保证了只有获得锁的线程才能够操作锁定的内存区域。JVM内部实现了很多种锁机制,有偏向锁、轻量级锁和互斥锁。有意思的是除了偏向锁,JVM实现锁的方式都用了循环 CAS,即当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。2、使用循环CAS实现原子操作JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行原创 2022-03-10 10:08:07 · 118 阅读 · 0 评论 -
008 synchronized锁的升级
Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在 Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状 态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。1、偏向锁1.1 偏向锁获得过程HotSpot[1]的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并 获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的原创 2022-03-09 18:04:51 · 133 阅读 · 0 评论 -
007 synchronized用的锁存储在Java对象头里,任何对象都有一个monitor与之关联
1、Java中的每一个对象都可以作为锁具体表现为以下3种形式。(1)对于普通同步方法,锁是当前实例对象。(2)对于静态同步方法,锁是当前类的Class对象。(3)对于同步方法块,锁是Synchonized括号里配置的对象。当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。那么锁到底存在哪里呢?锁里面会存储什么信息呢?从JVM规范中可以看到Synchonized在JVM里的实现原理,JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。任何对象都有 一原创 2022-03-09 17:50:34 · 711 阅读 · 0 评论 -
006 volatile的禁止指令重排序特性解决单例的双重校验锁(DCL)的懒汉模式的问题
1、首先看下双重校验锁的懒汉模式来实现的单例(多线程时有问题的)public class Singleton { private static Singleton instance; private String name; private Singleton() { this.name = "我是name属性的值"; } public static Singleton getInstance() { if (instance == null) {原创 2022-03-09 15:01:47 · 231 阅读 · 0 评论 -
005 volatile不能保证原子性之i++操作
1、下面启动了1000个线程对volatile修饰的变量进行i++操作,我们可能会想每一个线程都+1,当1000个线程都执行完+1操作之后结果应该是1000,但是执行代码试试,结果可能不是1000。这说明volatile不是原子性的。public class Counter { public volatile static int count = 0; public static void main(String[] args) { // 同时启动1000个线程,去进行i++计算,看看实际结原创 2022-03-09 11:15:55 · 3421 阅读 · 0 评论 -
004 volatile在JSR中的定义
volatile在JSR(是Java Specification Requests的缩写,意思是Java规范提案)中的定义:The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that .原创 2022-03-04 14:59:49 · 297 阅读 · 0 评论 -
003 Java并发编程之volatile的内存语义及内存语义的实现(内存屏障来禁止指令重排序)
1、JMM通过控制主内存与每个线程的本地内存之间的交互,为Java程序员提供内存可见性保证1.1 线程间的通信和同步是并发编程的2大问题:(1)线程之间的通信机制有两种:共享内存和消息传递。Java并发中线程之间的通信采用的是共享内存模型。(2)同步是指程序中用于控制不同线程间操作发生相对顺序的机制。1.2 Java线程之间的通信由Java内存模型(简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的原创 2022-03-03 15:33:58 · 267 阅读 · 0 评论 -
002 Java并发编程之volatile“可见性”的定义和实现原理(在硬件层面上Lock前缀的汇编指令)
Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令。“可见性”的定义:volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。“可见性”的实现原理:有volatile变量修饰的共享变量进行写操作的时候会多出Lock前..原创 2022-03-02 22:53:39 · 279 阅读 · 0 评论 -
001 并发编程带来的上下文切换和死锁问题
并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题。关于上下文切换,CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。关于死锁,线程t1和线程t2互相等待对方释放锁,这时候就会出现死锁的.原创 2022-03-02 22:04:14 · 545 阅读 · 0 评论 -
网站并发量的计算方法
你想建设一个能承受500万PV/每天的网站吗? 500万PV是什么概念?服务器每秒要处理多少个请求才能应对?如果计算呢?PV是什么:PV是page view的简写。PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv。计算模型:每台服务器每秒处理请求的数量=((80%*总PV量)/(24小时*60分*60秒*40%)) / 服务器数量 。其中关键的参数是80%、40%。表...转载 2019-07-01 08:45:57 · 502 阅读 · 0 评论 -
线程间通信
http://ifeve.com/thread-signaling/https://blog.csdn.net/u011514810/article/details/77131296https://www.cnblogs.com/xdyixia/p/9386133.htmlhttps://www.cnblogs.com/hapjin/p/5492619.html转载 2021-01-25 11:27:21 · 87 阅读 · 0 评论 -
如何设计一个百万级用户的抽奖系统?
1、抽奖系统的背景引入本文给大家分享一个之前经历过的抽奖系统的流量削峰架构的设计方案。抽奖、抢红包、秒杀,这类系统其实都有一些共同的特点,那就是在某个时间点会瞬间涌入大量的人来点击系统,给系统造成瞬间高于平时百倍、千倍甚至几十万倍的流量压力。比如抽奖,有一种场景:某个网站或者APP规定好了在某个时间点,所有人都可以参与抽奖,那么可能百万级的用户会蹲守在那个时间点,到时间大家一起参与这个...转载 2019-07-01 09:53:01 · 220 阅读 · 0 评论 -
【高并发解决方案】1、高并发解决方案汇总
一、对于被频繁调用,更新频率较低的页面,可以采用HTML静态化技术二、图片服务器分离三、数据库集群和库表散列 mysql主从。m-m-s-s-s...(2个主,多个从。多个从使用负载均衡。主写入数据,从读取数据)四、缓存。众多的缓存框架五、负载均衡。nginx,lvs,F5六、搜索用单独的服务器,搜索框架七、使用MQ服务器...转载 2019-08-20 11:12:16 · 183 阅读 · 0 评论 -
【高并发】秒杀系统高并发请求排队处理
今天无意中看见了这位兄弟的文章通过请求队列的方式来缓解高并发抢购(初探) 但文章最后说并发超过500 就会出现超发,看了下代码,的确有这个问题抽空简单完善了下,经压力测试后发现暂无超发现象, 下面为我的代码,有不足之处请指正交流:1.请求参数封装,有个随机的用户ID 用来区分不同用户的请求:import java.util.Random;public clas...转载 2019-06-28 16:35:08 · 3940 阅读 · 1 评论 -
如何设计一个秒杀系统
说起秒杀,我想你肯定不陌生,从双十一购物到春节抢红包,再到逢年过节抢⻋票,“秒杀”的场景在我们的生活中处处可⻅。简单来说,秒杀就是在同一个时刻有大量的请求,争抢购买同一个商品并完成交易的过程。不管校招,还是社招,如何设计一个秒杀系统的面试题经常出现,如果懂得其中原理,就可以对答如流,不过涉及到一些瓶颈优化,有些同学就未必都能答出。面试官:简单说一下秒杀系统的设计思路?这种题目,小菜...转载 2019-08-20 11:10:01 · 139 阅读 · 0 评论 -
阿里的互联网三高架构演进
前言作为一名专业的 Java 开发者,如何在并发场景中写出优良的代码,是一道绕不开的坎,也是考量一个 Java 开发者功底的关键技术。因此,不难发现 Java 并发问题一直是各个大厂面试的重点之一,然而我发现很多候选人在面试时,常常表示对各种并发原理核心学习笔记(关注公众号:麒麟改bug获取)一脸懵逼,好像知道一些却又讲不清楚,最终导致面试失败。于是发奋学习,啃大部头书又发现理论太多,头疼。其实 Java 的并发问题虽然内容繁杂,然而整个脉络还是很清晰的。什么是高并发高并发指的是系统同时处理很多转载 2021-12-30 14:45:50 · 1214 阅读 · 0 评论 -
什么是高并发 ,详细讲解
一、什么是高并发高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。吞吐量:单位时间内处理的请求数量。QPS..转载 2021-12-29 17:56:34 · 5322 阅读 · 0 评论 -
【高并发解决方案】4、秒杀系统架构分析与实战
1 秒杀业务分析 正常电子商务流程 (1)查询商品;(2)创建订单;(3)扣减库存;(4)更新订单;(5)付款;(6)卖家发货 秒杀业务的特性 (1)低廉价格;(2)大幅推广;(3)瞬时售空;(4)一般是定时上架;(5)时间短、瞬时并发量高; 2 秒杀技术挑战假设某网站秒杀活动只推出一件商品,预计会吸引1万人参加活动,也就说最大并发请求数是10000,秒...转载 2019-08-20 11:14:43 · 142 阅读 · 0 评论 -
Java中Thread.yield详解
Thread.yield( )方法:使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择。这时候,“当前” 也就是刚刚的那个线程还是有可能会被再次执行到的。public class YieldTest extends Thread { public YieldTest(String name) { super(name); } @SuppressWarnings("static-access") @Override public void ru原创 2021-02-18 13:43:11 · 471 阅读 · 1 评论 -
支撑日活百万用户的高并发系统,应该如何设计其数据库架构?
目录:1.用一个创业公司的发展作为背景引入2.用多台服务器来分库支撑高并发读写3.大量分表来保证海量数据下查询性能4.读写分离来支撑按需扩容及性能提升5.高并发下的数据库架构设计总结“ 这篇文章,我们来聊一下对于一个支撑日活百万用户的高并系统,他的数据库架构应该如何设计?看到这个题目,很多人第一反应就是:分库分表啊!但是实际上,数据库层面的分库分表到底是用来干什...转载 2019-07-02 17:58:50 · 246 阅读 · 0 评论 -
多线程读数据写到并发队列中,再起一个线程轮询从队列中取数据写到文件中
最近项目有个需求,对数据库中的号码进行检查,检查号码状态是否正常,检查方法需要依赖接口,每个号码调一次http接口,基本思路:1,轮询分页查询数据库,取号码2,对取出的号码循环调接口查询3,接口结果记录到文件中由于最初没有考虑大量号码的情况,使用的是单线程处理,当时2W号码用了4个小时,简直跑废了的感觉,可能接口返回比较慢接近1s后边就使用了多线程处理,网上查了下,基本都是...转载 2019-10-16 18:01:42 · 812 阅读 · 0 评论 -
乐观锁与悲观锁——解决并发问题
引言为什么需要锁(并发控制)? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。典型的冲突有:丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6...转载 2018-11-02 17:07:41 · 113 阅读 · 0 评论 -
Java 4种线程池(ExecutorService)使用
1、new Thread的弊端执行一个异步任务你还只是如下new Thread吗?new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub }}).start();那你就out太多了,new Thread的...转载 2018-12-18 09:29:55 · 187 阅读 · 0 评论 -
究竟啥才是互联网架构“高可用”
原创 58沈剑 架构师之路 2016-12-05 08:36一、什么是高可用高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。假设系统一直能够提供服务,我们说系统的可用性是100%。如果系统每运行100个时间单位,会有1个时间单位无法提供服务,我们说系统的可用性是99%。很多公司的高可用目标是4个9,也就是99.99%,这就意味着,系统的年停机时间为8.76个小时。百度的搜索首页,是业内公认.转载 2021-12-29 17:52:27 · 117 阅读 · 0 评论