死锁和代码的性能可伸缩性问题

如下会发生死锁,当A和B线程调用transferMoney的时候等着A向B转账,和B向A转账,就会产生死锁A和B都持有锁

在这里插入图片描述
以下代码定义了锁的顺序,消除了死锁可能行,System.identityHashCode返回Object.hashCoded,但是极少数情况下会有值相等的情况,所以有一个Tie-Breaking,保证了每次随机有一个线程获得这个锁,比如A先来,获得tieLock锁,再获得from和to,那么线程B就不能获得tieLock锁了 System.identityHashCode出现散列相等可能性很低,所以最小代价保证最大安全
在这里插入图片描述
出租车先获取location,先获取地点判断是否到达,到达了通知dispatcher,先获取taix的锁,然后获取dispatcher的锁,同理调用image的线程先得到dispatcher、的锁,然后获得taxi锁,两个线程按照不同顺序获得锁,产生死锁。
在这里插入图片描述

以上可以看出,排除死锁的方式是判断哪个方法有两个同步,但是上面的taxi只能看见一个同步方法,暗藏一个同步,所以排查困难,可以用以下的开放调用来避免产生死锁,开放调用是指调用方法不用同步,如下,四个锁分别在不同的对象或者类,尽量用开放调用锁
在这里插入图片描述

有一个纠结的问题,等待过程持有锁,导致死锁,如果操作运行结束后释放锁,导致其他线程开启服务,解决思路,服务状态关闭前一直持锁,其他线程不得不等待,等关闭操作结束,开放调用结束,执行关闭操作的线程才能访问服务。

性能和可伸缩性
线程之间的协调(加锁、触发信号、内存同步),增加的上下文切换,线程创建销毁,线程调度。如果过多使用线程,这些开销会超过高吞吐量,响应性,计算能力所带来的性能提升,有时候比实现相同功能的串行程序性能还要差。从监视性能角度看,cpu要尽可能保持忙碌。性能指标:服务、延迟时间,吞吐率、效率、可伸缩性’容量。时间衡量程序运行速度,其他衡量处理能力。

在这里插入图片描述
加速比Speedup,F代表必须串行执行的部分,N是CPU数量。如果程序中有50%需要串行执行,最高加速比是2,程序有10%的计算需串行,最高加速比就是52.6%

在这里插入图片描述
加入N个线程正在执行下面的代码,表面看起来处理器越多,处理任务越多,但其中包含了一个串行部分,队列获取任务,队列进行并发访问时采用同步机制维持队列的完整性
在这里插入图片描述单个任务 的时间 = 执行Runnable.time + take.time 。串行部分往往必不可少的,比如对结果进行处理,比如流的collect(Collects.toList)就是串行的
提高性能和可伸缩性的办法就是

  • 减少锁的竞争
  • 减少锁持有时间
  • 降低锁持有频率
  • 是用带有协调机制独占锁

缩小锁的范围(“快进快出”)

可以将一些与锁无关代码移除同步代码块。比如降低锁的持有时间,可以将吞吐量提高,如下代码中的只有map需要加锁,因为只有location被修改啊,但是却把整个userLocationMarches放进去了
在这里插入图片描述
在上面代码步骤包括实例化StirngBuilder对象,添加字符串,结果实例化为String对象,获取了位置就可以将正则表达式与位置字符串进行匹配,而构建字符串和正则匹配的时候不需要访问共享状态,所有不需要任何锁,所以步骤移出同步代码块,这样减少了串行的代码数量了。
在这里插入图片描述
get方法是根据key查找value,所以计算出一个key就得上锁,clear是清空整个表,找一个key,将头节点置null,所以锁位Nkey个
在这里插入图片描述

减小锁的粒度
分解一个锁为多个,每个锁保护一个变量,提高可伸缩性,降低每个锁被请求频率
在这里插入图片描述
转化为以下,如果add调用2次,那么每个锁只有1次使用在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值