标题格
1、线程的五种状态
2、Java 8 优化CAS性能
3、如何对每秒上千场景下的分布式锁高并发优化
4、并发问题的AQS理解
5、非公平锁
6、消息的优缺点、选择哪种
7、TCC分布式事务
1、线程的五种状态
1)、新建
当new创建一个线程,例如new thread(r),线程还没开始运行,处于新建状态。
2)、就绪
新建的新线程并不会自动运行,要执行需要调用start()方法创建线程运行的系统资源,返回后,此时线程就处于就绪状态。
但是处于就绪状态的线程也并不是就能立即执行run()方法。因为线程必须同其他线程竞争CPU时间,获得CPU时间才能运行线程。(线程数>CPU数)
3)、运行
当线程获得CPU时间,进入运行状态,执行run()方法。
4)、阻塞
线程运行过程中,可能由于很多原因进入阻塞状态:
1)、线程通过调用sleep方法进入睡眠状态;
2)、线程试图获得一个锁,但是该锁被其他线程持有;
3)、线程在等待某个处罚条件;(例如定时启动线程)
所谓阻塞就是正在运行的线程没有结束,暂时让出CPU,其他处于就绪的线程就获得CPU时 间,进入运行状态。
5)、死亡
两个原因导致线程死亡:
1)、run()方法正常退出而自然死亡;
2)、一个未捕获的异常终止了run方法而使线程猝死;
用isAlive返回true,则线程可运行或被阻塞。返回false,则线程死亡或者new状态且不是可运行的。
2、Java 8 优化CAS性能
1)、什么是CAS
例如一个多个线程对一个变量不停累加/累减1,例如 private int data = 0; data ++; 当多线程执行就可能会发生错误,结果并不一定会准确。 最开始的解决
办法是加锁 public synchronized void add() { data ++}; 但是一个简单的Java操作用synchronizes大材小用。 所以现在用了atomic原子类
private atomicInteger data = new AtomicInteger(0); data.incrementAndGet(); 该方法即使用了CAS机制。
CAS(compare and Set):多个线程都获取data当前值,走一个CAS的原子操作,然后所有线程拿当前值比较data的值,相等,则过滤,不相等,则进入
下一个循环。
2)、Java 8的优化
如果线程太多,可能会进入一个无线重复的循环中。所以Java 8推出了分段CAS以及自动分段迁移机制:发现并发线程过多,就会内部分Cell
数组,每个数组都是一个数值的分段。 然后一部分线程执行分段1,一分部线程执行分段2...减轻了循环的次数。 如果某个Cell的value执行CAS失败,就会
找其他Cell分段执行CAS操作。
3、如何对每秒上千场景下的分布式锁高并发优化
如果对一个商品不加锁,就可能出现库存超卖的情况(库存15,2个用户各买10个,没有锁的情况可能出现-5的最终库存)。所以我们可以用:4
悲观锁、乐观锁、分布式锁、队列串行化、异步队列分散、Redis原子操作等等...
现在限定了分布式锁,有个问题:如果一套请求-下单需要20毫秒,1秒就只能容许50个用户对商品的排队等候情况(分布式锁),不能做到每秒上千场景。
解决方法:首先理解Java的ConcurrentHashMap的源码和底层原理,核心就是分段加锁。所以我们可以把1000个商品分成20段库存,客户端
1000个请求进服务端的时候,随机分给20段库存,每个分段各自加锁执行...但是某个下单请求,加锁后发现分段库存不足。那么必须释放锁,换以一个分段库存,再测尝试加锁处理。
这个方法主要缺点就是太复杂
4、并发问题的AQS理解
AQS(AbstractQueuedSynchronizer,抽象队列同步器)是Java并发包的基础类。ReentrantLock,加锁和解锁的核心组件(ReentrantLock lock = new ReentrantLock() lock.lock();加锁 lock.unlock() 解锁)。
AQS对象内部有个变量state(int类型)代表加锁对象,初始值0(加锁状态值=1)。AQS还有个关键变量,记录当前加锁的是哪个线程,初始值null。
AQS还有一个等待队列,专门放加锁失败的线程(CAS机制加锁机制)。
一句话总结:就是一个并发包的基础核心组件,实现各种锁,各种同步组件的。
5、非公平锁
在加锁过程,线程1运行,线程2处于等待队列。 线程1运行结束,结果线程3抢先于线程2进行。这就是非公平锁的简单含义。
在ReentrantLock lock = new ReentrantLock()默认的就是非公平锁,构造函数中加入true:ReentrantLock lock = new ReentrantLock(true)。
公平锁原则就是线程3就绪后,会先查看等待队列是否有线程,有就排队。
6、消息的优缺点、选择哪种
常见的消息插件有Kafka、ActiveMQ、RabbitMQ、RocketMQ...
优点:
解耦,使得子系统之间的耦合关系降低,只需要关注消息的发送与接收,不用担心子系统1挂了以后对子系统2产生影响。
异步,系统直接的数据传输不需要直接请求,直接发送消息,其他系统接收消息,返回,速度大大提高。
削峰,消息插件控制着请求数量,到达系统的数量/到数据库的数量。
缺点:系统可用性降低、系统复杂度提高、一致性问题。
ActiveMQ社区不活跃,要死的节奏。RabbitMQ是用erlang语言写的,很多人不能研究和掌控,但是对于小公司来说没问题。RocketMQ阿里的也可以。大数据领域用Kafka是业内标准。
7、TCC分布式事务
使用springcloud微服务,也有可能各个服务之间,没有形成一个整体的事务
分步实现
1)、try阶段:多个服务之间,在操作的时候对数据库的操作都是一个"预"操作阶段,锁定某个资源,冻结某部分资源等(把改变的数据先存临时表)
2)、confirm阶段:如果服务全部通过,依靠TCC分布式事务框架来执行---加入一个confirm类,提供一个接口,将刚刚的临时表数据,变为对数
据库真实的操作。(完成所有逻辑)
3)、Cancel阶段:如果某个服务挂了---也是提供一个接口,将临时表中的数据,恢复到原数据库中。(回滚所有逻辑)
该事务适用于同步操作
该随笔分类为公众号笔记,仅做笔记记录,加深记忆以及方便用时查找,非抄袭,非盈利。
参考:纯洁的微笑、石杉的架构笔记、java版web项目、架构师之路、springForAll社区等公众号。