转:java高并发学习记录-死锁,活锁,饥饿
|
死锁
两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
为什么会产生死锁:
① 因为系统资源不足。
② 进程运行推进的顺序不合适。
③ 资源分配不当。
产生死锁的条件有四个:
① 互斥条件:所谓互斥就是进程在某一时间内独占资源。
② 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
③ 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
④ 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁:
避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。
只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。
避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。
![]() 饥饿 一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。
解决饥饿的方案被称之为“公平性” – 即所有线程均能公平地获得运行机会。
Java中导致饥饿的原因:
① 高优先级线程吞噬所有的低优先级线程的CPU时间。
② 线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前持续地对该同步块进行访问。
③ 线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的wait方法),因为其他线程总是被持续地获得唤醒。
在Java中实现公平性方案,需要:
① 使用锁,而不是同步块。
② 公平锁。
③ 注意性能方面。
详细学习文章
饥饿和公平:
活锁 任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。
活锁的例子:
单一实体的活锁
例如线程从队列中拿出一个任务来执行,如果任务执行失败,那么将任务重新加入队列,继续执行。假设任务总是执行失败,或者某种依赖的条件总是不满足,那么线程一直在繁忙却没有任何结果。
协同导致的活锁
生活中的典型例子: 两个人在窄路相遇,同时向一个方向避让,然后又向另一个方向避让,如此反复。
通信中也有类似的例子,多个用户共享信道(最简单的例子是大家都用对讲机),同一时刻只能有一方发送信息。发送信号的用户会进行冲突检测, 如果发生冲突,就选择避让,然后再发送。 假设避让算法不合理,就导致每次发送,都冲突,避让后再发送,还是冲突。
计算机中的例子:两个线程发生了某些条件的碰撞后重新执行,那么如果再次尝试后依然发生了碰撞,长此下去就有可能发生活锁。
活锁的解决方法:
解决协同活锁的一种方案是调整重试机制。
比如引入一些随机性。例如如果检测到冲突,那么就暂停随机的一定时间进行重试。这回大大减少碰撞的可能性。 典型的例子是以太网的CSMA/CD检测机制。
另外为了避免可能的死锁,适当加入一定的重试次数也是有效的解决办法。尽管这在业务上会引起一些复杂的逻辑处理。
比如约定重试机制避免再次冲突。 例如自动驾驶的防碰撞系统(假想的例子),可以根据序列号约定检测到相撞风险时,序列号小的飞机朝上飞, 序列号大的飞机朝下飞。
|
转:java高并发学习记录-死锁,活锁,饥饿的更多相关文章
- Java多线程高并发学习笔记(一)——Thread&Runnable
进程与线程 首先来看百度百科关于进程的介绍: 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体.它不只是程序的代码,还包括当前的 ...
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock. 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍Re ...
- imooc课程:Java高并发秒杀API 记录
Java高并发秒杀API之业务分析与DAO层 Java高并发秒杀API之Service层 Java高并发秒杀API之web层 Java高并发秒杀API之高并发优化 除了并发部分外的这个web开发的总结 ...
- java高并发系列 - 第22天:java中底层工具类Unsafe,高手必须要了解
这是java高并发系列第22篇文章,文章基于jdk1.8环境. 本文主要内容 基本介绍. 通过反射获取Unsafe实例 Unsafe中的CAS操作 Unsafe中原子操作相关方法介绍 Unsafe中线 ...
- Java高并发系列——检视阅读
Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- Java高并发--原子性可见性有序性
Java高并发--原子性可见性有序性 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 原子性:指一个操作不可中断,一个线程一旦开始,直到执行完成都不会被其他线程干扰.换 ...
- Java高并发 -- 并发扩展
Java高并发 -- 并发扩展 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 死锁 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象, ...
- Java高并发--AQS
Java高并发--AQS 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 AQS是AbstractQueuedSynchronizer的简称,直译过来是抽象队列同步器. ...
随机推荐
- mysql 创建连接是 Cannot create PoolableConnectionFactory (Unknown character set: 'utf8mb4')
Cannot create PoolableConnectionFactory (Unknown character set: 'utf8mb4') maven 依赖换版本 <dependenc ...
- CodeForces 35D Animals
G - Animals Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- am335x omap serial 驱动分析
am335x 自身的 uart 驱动集成在 kernel 的 arch/arm/mach-omap2/ 里面. 文件是 arch/arm/mach-omap2/serial.c // 看到最底部 om ...
- debug宏起作用应用
在linux内核中重新定义了printk,如pr_debug,dev_dbg等.要使用这些宏函数就需要定义DEBUG. 详见:kernel printk信息显示级别 那么DEBUG该定义在什么地方呢? ...
- 示例 - 如何在Console应用程序中应用SpiderStudio生成的DLL?
以前面生成的XML/JSON互转DLL为例, 我们写一个Console Appliction来做这件事情, 步骤如下: 1. 创建Console Project 2. 引入www.utilities_ ...
- javascript父、子页面交互小结
帧用来存放子页面,既可以是iframe,又可以是frameset.window对象是全局对象,页面上的一切函数和对象都在它的作用域里. 1.parent代表父窗口.如果父窗口又存在若干层嵌套, ...
- C++ 运算符重载一(二元运算符重载)
//二元运算符重载 #include<iostream> using namespace std; class Point { public: Point(int x,int y){ th ...
- sql 使用整理
今天使用视图查询东西,为了方便直接select * 查出来的都行全部都错乱了,看来sql 超过20个以上的字段为了效率和安全,禁止用select * -------------查一个表的所有字段的-- ...
- Tensorflow之快速加载MNIST数据集
from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf def myprint(v): p ...
- Unity UGUI实现Button按钮长按状态的判断
代码: using UnityEngine.EventSystems; using System.Collections; /// <summary> /// 脚本位置:UGUI按钮组件身 ...
