转:java高并发学习记录-死锁,活锁,饥饿


死锁

两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

为什么会产生死锁:

① 因为系统资源不足。

② 进程运行推进的顺序不合适。

③ 资源分配不当。

产生死锁的条件有四个:

① 互斥条件:所谓互斥就是进程在某一时间内独占资源。

② 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

③ 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。

④ 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁:

避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。

只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。

避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。

饥饿

一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。

解决饥饿的方案被称之为“公平性” – 即所有线程均能公平地获得运行机会。

Java中导致饥饿的原因:

① 高优先级线程吞噬所有的低优先级线程的CPU时间。

② 线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前持续地对该同步块进行访问。

③ 线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的wait方法),因为其他线程总是被持续地获得唤醒。

在Java中实现公平性方案,需要:

① 使用锁,而不是同步块。

② 公平锁。

③ 注意性能方面。

详细学习文章

饥饿和公平:

http://ifeve.com/starvation-and-fairness/#header

活锁

任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。


活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;活锁有可能自行解开,死锁则不能。

活锁的例子:

单一实体的活锁

例如线程从队列中拿出一个任务来执行,如果任务执行失败,那么将任务重新加入队列,继续执行。假设任务总是执行失败,或者某种依赖的条件总是不满足,那么线程一直在繁忙却没有任何结果。

协同导致的活锁

生活中的典型例子: 两个人在窄路相遇,同时向一个方向避让,然后又向另一个方向避让,如此反复。

通信中也有类似的例子,多个用户共享信道(最简单的例子是大家都用对讲机),同一时刻只能有一方发送信息。发送信号的用户会进行冲突检测, 如果发生冲突,就选择避让,然后再发送。 假设避让算法不合理,就导致每次发送,都冲突,避让后再发送,还是冲突。

计算机中的例子:两个线程发生了某些条件的碰撞后重新执行,那么如果再次尝试后依然发生了碰撞,长此下去就有可能发生活锁。

活锁的解决方法:

解决协同活锁的一种方案是调整重试机制。

比如引入一些随机性。例如如果检测到冲突,那么就暂停随机的一定时间进行重试。这回大大减少碰撞的可能性。 典型的例子是以太网的CSMA/CD检测机制。

另外为了避免可能的死锁,适当加入一定的重试次数也是有效的解决办法。尽管这在业务上会引起一些复杂的逻辑处理。

比如约定重试机制避免再次冲突。 例如自动驾驶的防碰撞系统(假想的例子),可以根据序列号约定检测到相撞风险时,序列号小的飞机朝上飞, 序列号大的飞机朝下飞。

时间: 2024-07-31 09:15:02

转:java高并发学习记录-死锁,活锁,饥饿的相关文章

java高并发学习-死锁(一)

死锁发生的必要条件: 1.互斥条件 2.请求和保持条件 3.资源不剥夺条件 4.环路等待条件 多线程的最佳并发实践; 1. 使用本地变量 2.使用不可变类 3.最小化锁的作用域范围 : S = 1/(1-a+a/n)   (阿木达尔定律) 其中,a为串行计算部分所占比例,n为并行处理结点个数.这样,当a=0时,最大加速比s=n:当a=1时,最小加速比s=1:当n→∞时,极限加速比s→ 1/a,这也就是加速比的上限.例如,若串行代码占整个代码的25%,则并行处理的总体性能不可能超过4.这一公式已被

imooc课程:Java高并发秒杀API 记录

Java高并发秒杀API之业务分析与DAO层 Java高并发秒杀API之Service层 Java高并发秒杀API之web层 Java高并发秒杀API之高并发优化 除了并发部分外的这个web开发的总结:https://www.imooc.com/video/11737 springmvc运行流程 BOOTSTRAP 和 JS 的使用技巧.(模块化.不混乱.抽取字典方便修改) JQ插件(countDown && cookie 等) 原文地址:https://www.cnblogs.com/a

Java高并发编程(一)

1.原子量级操作(读.++操作.写分为最小的操作量单位,在多线程中进行原子量级编程保证程序可见性(有序性人为规定)) 由于某些问题在多线程条件下:产生了竞争的问题,(例如:在多线程中一个简单的计数器增加)如果在程序中不采用同步的机制,那么在程序的运行结果中,多个线程在访问此资源时候,产生Racing.解决这个问题,采用某种方式阻止其他线程在该线程使用该变量的时候使用该变量 采用原子级操作:1.采用加锁的机制(最好的操作)2.Java.concurrent.atomic包包含一些原子量操作:Ato

Java高并发是不是你的菜??

自从JAVA5.0增加了最初由DougLea编写的高质量的.广泛使用的.并发实用程序util.concurrent并变成了JSR-166的新包之后,在Java内置所提供的类库中,就提供了越来越多的并发编程的实用工具类.学习并掌握这些技术对于专注于Java并发编程的开发人员来讲是基本的公里,随着Java版本的不断更新与改进,开发人员可以通过Java新版本所带来的新特性,无需从头重新编写并发程序工具类. 我们该学习Java并发嘛? 我们该如何学习Java并发? CPU这么多核了,我们如何更好的利用?

Java高并发秒杀API之业务分析与DAO层

课程介绍 高并发和秒杀都是当今的热门词汇,如何使用Java框架实现高并发秒杀API是该系列课程要研究的内容.秒杀系列课程分为四门,本门课程是第一门,主要对秒杀业务进行分析设计,以及DAO层的实现.课程中使用了流行的框架组合SpringMVC+Spring+MyBatis,还等什么,赶快来加入吧! 第1章 课程介绍 本章介绍秒杀系统的技术内容,以及系统演示.并介绍不同程度的学员可以学到什么内容. 第2章 梳理所有技术和搭建工程 本章首先介绍秒杀系统所用框架和技术点,然后介绍如何基于maven搭建项

【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference

[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference AtomicReference无法解决上述问题的根本是因为对象在修改过程中,丢失了状态信息.对象值本身与状态被画上了等号.因此,我们只要能够记录对象在修改过程中的状态值,就可以很好的解决对象被反复修改导致线程无法正确判断对象状态的问题. AtomicStampedReference正是这么做的.它内部不仅维护了对象值,还维护了一个时间戳(我这里把它

【实战Java高并发程序设计 5】让普通变量也享受原子操作

[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象引用:AtomicStampedReference [实战Java高并发程序设计 4]数组也能无锁:AtomicIntegerArray 有时候,由于初期考虑不周,或者后期的需求变化,一些普通变量可能也会有线程安全的需求.如果改动不大,我们可以简单地修改程序中每一个使用或者读取这个变量的地方.但显然

Java高并发,如何解决,什么方式解决

对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧. 为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1.同步和异步的区别和联系 所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到 返回的值或消息后才往下执行其它的命令. 异步,执行完函数或方法

【实战Java高并发程序设计 1】Java中的指针:Unsafe类

是<实战Java高并发程序设计>第4章的几点. 如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现.现在,就让我们更进一步看一下它把! public final boolean compareAndSet(int expect, int update){ returnunsafe.compareAndSwapInt(this, valueOffset, expect, update); } 在这里,我们看到一个特殊的变