并发编程原则与技术(五)——避免并发编程活跃度危险

如何用Lmcache+vllm优化KVcache存储?CPU与SSD性能实测对比 本文通过实测对比,详细介绍了如何利用Lmcache+vLLM将大模型推理中的KV Cache卸载至CPU内存或SSD硬盘,以解决长上下文场景下的GPU显存瓶颈。测试数据显示,CPU卸载方案在首字延迟(TTFT)上显著优于SSD方案,但SSD方案在存储成本上更具优势。文章提供了完整的配置指南、性能数据分析和生产环境选型建议。 阅读详情
 
并发编程原则
(五)
避免并发编程活跃度危险
前 言:
在这个系列文章中的前几篇文章中,我们的讨论主要围绕着在并发环境下如何确保对共享对象的访问安全。但是很多情况下安全性与活跃度是一对矛盾。通常我们使用锁来保证线程安全,但是如果锁被滥用可能引起系统的“活跃度”的下降,使系统的响应减缓以及吞吐量的降低。更严重的情况是可能会引起各种活跃度危险,比如:CPU饥饿,弱响应,活锁甚至死锁。
(1)、死锁:
在所有的并发编程活跃度问题中死锁无疑是最为严重的,在Java编写的系统中更为严重,因为Java应用程序不能从死锁中恢复,唯一的办法就是重新启动服务器,然后默默向上苍祷告不要再出现这样的噩梦。
我想凡是正规计算机专业毕业的朋友都会学习操作系统课程,在操作系统中一定会接触过经典的“哲学家进餐”问题,这个问题很好的揭示了死锁。当一个线程永远占有一个锁,而其他线程尝试去获得这个锁,那么他们将会被永远的阻塞。这种情况便形成了一种死锁情况,这种死锁是一种简单形式的死锁,它由环路锁依赖引起的。死锁是很难被发现的,它不会随时爆发,而只会在某些情况下突然爆发,而且很不幸这些情况通常都是在高负载情况下出现。
1、              锁顺序死锁:
请看下面的1.1.1代码所示:
public class DeadLock{
 private final Object left=new Object();
 private final Object right=new Object();
 public void leftlock(){
synchronized(left){
 synchronized(right){
     doSomthig();
 }
}
 }
 public void rightlock(){
synchronized(right){
 synchronized(left){
    doSomthing();
 }
}
 }
}
当我们在多线程环境下运行上述代码后,马上就会出现死锁。造成这种死锁的原因就是:两个线程试图以不同的顺序获得多个相同的锁。也就是说上面的代码会造成获取left和right锁的线程互相等待,而又互不相让的情况,造成程序停滞不前无法运行。因此如果所有线程以通用的固定顺序获取锁,程序将不会出现锁顺序死锁。
2、              动态的锁顺序死锁:
有时候你并不能一目了然能看出哪里存在死锁隐患,这就是所谓的动态的顺序死锁。如下面1.1.2代码所示:
 public void transfermoney(Account fromaccount,
Account toaccount,
BigDecimal amount) throws Exception{
      synchronized(fromaccount){
        synchronized(toaccount){
          if(fromaccount.getBalance().compareTo(amount)<0){
            throw new Exception(“Balance insufficiency!”);
          }
          else{
            fromaccount.debit(amount);
            toaccount.credit(amount);
          }
        }
      }
}
上面的代码看起来所有的线程都是通过相同的顺序来获取锁,但是事实上锁的顺序取决于传递给transfermoney的参数顺序,如果有两个线程同时调用transfermoney并且以下面的顺序调用:
A:transfermoney(myaccount,youraccount,new BigDecimal(10));
B:transfermoney(youraccount,myaccount,new BigDecimal(20));
在偶发时序中,第一个线程获得myaccount的锁,并等待youraccount的锁,然而此时第二个线程已经持有youraccount的锁,并且正在等待myaccount的锁。这样就动态的形成了锁顺序死锁。我们可以采用下面1.1.3代码来改进上面的程序以减少死锁的危险:
   private static final Object tielock=new Object();
   public void transfermoney(final Account fromaccount,
                          final Account toaccount,
                          final BigDecimal amount) throws Exception{
      class Helper{
        public void transefer() throws Exception{
          if(fromaccount.getBalance().compareTo(amount)<0){
            throw new Exception(“Balance insufficiency!”);
           }
          else{
            fromaccount.debit(amount);
            toaccount.credit(amount);
          }
        }
      }
     int fromhash=System.identityHashCode(fromaccount);
     int tohash=System.identityHashCode(toaccount);
     if(fromhash<tohash){
       synchronized(fromaccount){
         synchronized(toaccount){
           new Helper().transfer();
         }
       }
     }
     else if(fromhash>tohash){
        synchronized(toaccount){
         synchronized(fromaccount){
           new Helper().transfer();
         }
       }
     }
     else{
        synchronized(tielock){
         synchronized(fromaccount){
            synchronized(toaccount){
               new Helper().transfer();
          }
         }
        }
     }
   }
上面代码中使用了System.identityHashCode方法来生成对象的hashcode,并且按照生成hashcode的大小决定加锁顺序,虽然加入了新的代码,但是这却能够减少死锁发生的可能性。通常情况下通过System.identityHashCode返回的hashcode不会出现相同的值,但是为了防止那极少数的情况,我们还加入了一个额外的测试锁tielock,如果两个对象返回的hashcode出现了相等的情况,这时通过强制要求在获取两个Account锁之前,先获取tielock锁,这样就能保证一次只有一个线程执行这个有风险的操作,从而减少死锁发生的可能性。
3、              协作对象间死锁:
如果一个对象的方法正在调用一个外部方法,而这个外部方法是一个需要持有锁的方法,这种情况可能就是死锁发生的一种警示。因为外部方法可能会获得其它锁(产生死锁风险),或者遭遇严重的超时阻塞。当持有锁时会延迟其它试图获得该锁的线程。如下面代码1.1.3所示:
class Taxi{
 private final Dispather dispather;
 private final Point location,destination;
 public Taxi(Dispather dispather){
    this.dispather=dispatcher;
 }
 public synchronized point getLocation(){
    return location;
 }
 public synchronized void setLocation(Point location){
    this.location=location;
    if(location.equals(destination)){
      dispatcher.notifyAvailable(this);
    }
 }
}
class Dispather{
 private final Set<Taxi> taxis;
 private final Set<Taxi> availableTaxis;
 public Dispather(){
    taxis=new HashSet<Taxi>();
    availableTaxis=new HashSet<Taxi>();
 }
 public synchronized void notifyAvailable(Taxi taxi){
    availableTaxis.add(taxi);
 }
 public synchronized Image getImage(){
    Image image=new Image();
    for(Taxi t:taxis){
      image.draw(t.getLocation());
    }
    return image;
 }
}
在上面的代码中在某种时序下会产生协作死锁。因为在调用setLocation方法时线程获取Taxi的锁,然后再获取Dispather的锁。类似的当调用getImage方法时线程先获取Dispather的锁,然后再获取Taxi的锁。这样就形成了锁顺序死锁。
以上我们讨论了三种死锁情形,这三种情形可以说都是锁顺序死锁,其中后两种是第一种情况的在复杂情况下的变体,因此也更加隐蔽更加难以发现。其中最复杂的是对象协作间死锁,为了有效的避免它,我们应该尽量采用“开放调用”。当调用的方法不需要持有锁时,这被称为开放调用。依赖开放调用的类会具有更好的行为,并且比那些需要获取锁才能调用的方法具有更容易与其它类合作的特点。这个原则可以进一步的发展,因为有时我们无法回避锁的使用,但是我们可以尽量减少锁的使用范围,是一个方法中的大部分代码成为开放的代码。本着这个原则我们通过以下1.1.4代码来优化上面1.1.3代码:
class Taxi{
 private final Dispather dispather;
 private final Point location,destination;
 public Taxi(Dispather dispather){
    this.dispather=dispatcher;
 }
 public synchronized point getLocation(){
    return location;
 }
 public synchronized void setLocation(Point location){
    boolean reachedDestination;
    synchronized(this){
      this.location=location;
      reachedDestination =location.equals(destination)
    }
     if(reachedDestination){
       dispatcher.notifyAvailable(this);
     }
 }
}
class Dispather{
 private final Set<Taxi> taxis;
 private final Set<Taxi> availableTaxis;
 public Dispather(){
    taxis=new HashSet<Taxi>();
    availableTaxis=new HashSet<Taxi>();
 }
 public synchronized void notifyAvailable(Taxi taxi){
    availableTaxis.add(taxi);
 }
 public Image getImage(){
    Set<Taxi> copy;
    synchronized(this){
      copy=new HashSet<Taxi>(taxis)
    }
    Image image=new Image();
    for(Taxi t:taxis){
      image.draw(t.getLocation());
    }
    return image;
 }
}
上面代码我们通过减少synchronized块的范围,使大部分代码成为开放代码,只让锁来保护那些共享变量。这样更加细化的加锁规范了加锁顺序,减小了死锁产生的可能性。
4、              资源死锁:
还有一种死锁不同于上面的死锁情况,这种死锁的产生源于对共享资源的竞争,所以称为资源死锁。这种死锁的常见场所就是数据库连接池的访问。对资源池的实现通常采用信号量,当资源池为空时资源池将被阻塞。假如有两个数据库连接池D1和D2,每个池中各有一个连接,有两个线程A/B,当线程A获取D1的连接并等待D2的连接,而线程B获取D2连接并等待D1的连接,这样就产生了资源死锁。资源池越大,这种情况发生的机率越小。另外应该记住有界池不应该同相互依赖的任务放在一起使用。
(2)、其它活跃度危险:
   尽管死锁使我们遇到的最主要的活跃度危险,并发编程中仍然存在其他一些并发活跃度危险,下面我将介绍几种:
1、CPU饥饿:
   当线程访问它需要的资源时却被永远的拒绝,以至于不能再继续进行,这就发生了饥饿。最常见的饥饿是CPU饥饿。在Java应用程序中,使用线程的优先级不当可能引起饥饿。在锁中无休止的构建也可能引起饥饿(无限循环,或者无休止的等待资源),因为其他需要这个所的线程将永远不会得到它。另外需要等待其他任务结果的任务是生成线程饥饿的重要来源。
 2、活锁:
    活锁是线程活跃度失败的另一种形式,尽管没有被阻塞,线程却仍然无法继续,因为它不断重试相同的操作,却总是失败。活锁通常来源于过渡的错误恢复代码,误将不可恢复的错误当作可修复的错误。因此我们在开发时要识别错误类别,当不可恢复的错误发生时就要“彻底的失败”,而不要试图去恢复。解决活锁的一种方案就是在重试中加入随机机制。比如我们熟悉的以太网的CSMA/CD机制,当两台机站采用相同的载波发送数据包,这时会发生冲突,机站发现冲突后会延迟一段时间后重发,如果它们都很默契的延迟一秒钟后重发,那么还会引发冲突,并且不断冲突下去。如果我们使各个机站采用一个随机组件来生成延迟时间,那么将会减少再次冲突的可能。在并发程序中,通过随机等待和撤销重试能够相当有效的避免活锁发生。
   除此之外还有很多活跃度危险,比如由于不良的锁管理策略引发的弱响应性,或者由于信号丢失引起的挂起等等。
 
机器人中的数值优化(十四)——罚函数法(Penalty Method)、障碍函数法(Barrier Method)、拉格朗日松弛法(Lagrangian Relaxation) 本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,下半部分介绍带约束的优化,中间会穿插一些路径规划方面的应用实例 阅读详情

相关推荐

手把手教你用GNU Radio和PlutoSDR搭建FM收音机(附完整流程图)

本文提供了一份详细的实践指南,教你如何使用GNU Radio和PlutoSDR搭建一个功能完整的FM收音机。从软硬件环境准备、核心流程图构建,到运行调试与效果优化,手把手带你完成从射频信号接收、下变频、FM解调到音频输出的全过程,是入门软件定义无线电(SDR)的绝佳实践项目。

weixin_29189377的博客 749

避免死锁的编码原则

1. 多个方法,操作同一张表的,统一操作该表的方法,更新此表用同一个方法,方法内使用多线程锁/分布式锁 2. 一次操作,操作多个表,每个模块统一操作顺序 3. 不要在循环里 调用写数据库的操作 4. 查询用with(nolock), 修改、删除(update\delete) where条件匹配主键 非聚集索引:UPDATE 可以走行级锁, WHERE条件不是主键或者索引, 即使强制走行级锁也走不了行级锁 错误示例: a. delete fro...

niu_mo_wang的专栏 951

LlamaIndex 入门实战

LlamaIndex是一个“数据框架”,用于帮助构建LLM应用程序。它提供了各种工具,包括数据连接器,用于摄取现有数据源和数据格式(API,PDF,文档,SQL等),以及用于将数据结构化(索引,图形)以便与LLM轻松使用的方式。此外,LlamaIndex还提供了高级的检索/查询接口,可以输入任何LLM输入提示,并返回检索到的上下文和增强知识的输出。它还允许与外部应用程序框架(如LangChain,Flask,Docker,ChatGPT等)轻松集成。

AIGC搞起 1万+

死锁预防、死锁避免、死锁检测

多个进程并发执行,由于竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法推进,这就是死锁现象。例如:系统中只有一台打印机和一台输入设备,若进程p1正在占用输入设备,同时又提出使用打印机的请求;而进程p2正在占用打印机,同时又提出请求输入设备的请求。这样两个进程相互无休止地互相等待,均无法继续执行,此时这两个进程进入死锁状态。①系统资源的竞争只有对不可剥夺资源的竞争(如打印机) 才可能产生死锁,对可剥夺资源的竞争是不会产生死锁的。②进程推进顺序非法进程在运行过程中,请求和释放资源的顺序不当,

weixin_44897707的博客 7372

新手DIY无人机,从电机到飞控,这份配件清单和避坑指南请收好

本文为无人机DIY新手提供从电机到飞控的完整配件清单和避坑指南。详细解析电机KV值选择、电调匹配、飞控系统调试等核心问题,帮助初学者避开常见雷区,顺利完成首飞。特别推荐FPV竞速机和航拍机的配件组合方案,并附赠实用调试命令和故障排查表。

weixin_27032989的博客 237

什么是程序死锁,如何预防

在并发程序设计中,死锁 (deadlock) 是一种十分常见的逻辑错误。通过采用正确的编程方式,死锁的发生不难避免。  死锁的四个必要条件 在计算机专业的本科教材中,通常都会介绍死锁的四个必要条件。这四个条件缺一不可,或者说只要破坏了其中任何一个条件,死锁就不可能发生。我们来复习一下,这四个条件是: •互斥(Mutual exclusion):存在这样一种资源,它在某个时刻只能被分配给一个执

xxaichishizi的博客 617

22、云数据中心网络(DCN)部署最佳实践

本文详细介绍了云数据中心网络(DCN)部署的最佳实践,涵盖SDN设计、服务网络规划、管理网络规划等方面。通过合理的架构设计、路由规划和组件协同,提升数据中心的自动化水平、可靠性及安全性,以满足不断增长的业务需求。

d6e7f8的博客 186

操作系统自学(十六)死锁以及预防死锁

死锁 死锁,饥饿,死循环 死锁:各个进程之间互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象 举个例子 比如哲学家进餐问题中,如果每个哲学家手中都拿一支筷子 他们会互相等待对方放下筷子 自己使用 这是就进入了死锁的状态 如果没有外界干预或者是操作系统的干预 他们会一直阻塞下去 再举个例子,假如两个人都想去厕所 他俩也不认识 然后他俩同时跨进厕所的门 他俩还都爱钻牛角尖 于是就互不相让 都在等着对方让步 所以他俩就一直僵持着 这时要是没有一个“智者”调解他俩 他俩就一直僵持下去。 饥饿由于长期

weixin_44302602的博客 598

Python爬虫实战:爬取携程旅游平台数据,我拆解了动态反爬+Cookie续命(附完整可运行代码)

反爬类型表现形式应对思路sign参数返回403/空数据逆向JS还原加密逻辑Cookie时效登录后1小时Cookie失效定时刷新Cookie/保存登录态行为检测爬取过快触发验证码模拟真人延时/随机点击IP封禁单IP爬取超50条数据被封付费代理池/降低请求频率爬取携程旅游平台数据的核心,不是“简单的HTTP请求”,而是“理解平台的反爬逻辑并合规适配”——从sign参数破解到Cookie维护,再到行为模拟,每一步都是对HTTP协议、前端加密、用户行为的深度理解。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1713

PY32F406K1CU6+I2C+ AT24C64 基本配置

【代码】PY32F406K1CU6+I2C+ AT24C64 基本配置。

sam的博客 90

死锁的四个必要条件以及如何避免死锁

死锁概念 如果一个进程集合中的每一个进程都在等待 只能由该进程集合中的其他进程才能引发的事件,那该进程集合就是死锁的;打个比方,一个女孩子手里有个洋娃娃,一个男孩子手里有个小汽车,女孩子想玩汽车,但又不想把洋娃娃让给男孩子,男孩子想玩洋娃娃,但也不想把汽车给女孩子玩,他们两个就这样僵持阻塞下去…这种情况就是资源死锁,洋娃娃和汽车就相当于是一个资源,而这个资源还是不可抢占资源,男女孩子相当于两个进程...

身在边城 心在编程 2715

【入坑存内计算一键指南】存内计算运算原理:算法优化、存储介质探究

本文探讨了存内计算及其面向的架构优化,尤其侧重于图算法优化和存内计算存储介质。文章介绍了存内计算的概念和意义,着重强调了存内计算解决了内存墙问题,提高了计算效率。针对图算法的优化,提出了基于位运算的创新方法,重塑了单源最短路径算法,并介绍了基于局部重叠度的链路预测算法优化设计。接着,文章详细讨论了存内计算存储介质,特别是非易失性存储器,比较了不同类型存储器的性能,并重点介绍了基于ReRAM的存内计算技术,包括其物理模型和交叉阵列结构。

一键难忘的博客 7066

JAVA并发编程实战-避免活跃度危险

目录思维导图1 死锁1.1 锁顺序死锁1.2 动态的锁顺序死锁1.3 协作对象间的死锁1.4 开放调用1.5 资源死锁2 避免和诊断死锁2.1 尝试定时的锁2.2 通过线程转储分析死锁3 其它的活跃度危险3.1 饥饿3.2 弱响应性3.3 活锁参考文献 思维导图 1 死锁 比如经典的哲学家进餐问题,很好的阐释了死锁。 如果每个人都拿起左边的筷子,等待右侧筷子可用,同时不放弃手中的筷子,将导致死锁产生。 当一个线程永远占有有一个锁,而其它线程尝试去占有这个锁,那么它们将永远被阻塞。 1.1 锁顺序死锁

qq_36566262的博客 710

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Thread专题(9/14) - 避免活跃度危险

安全性和活跃度通常互相牵制,我们一般用锁来保证线程安全、线程池和信号量来约束资源的使用,但使用不当就容易造成“死锁”和“资源死锁”。java不能从死锁中进行恢复。恢复应用程序健康的唯一方式就是中止或重启,然后寄希望于不要发生这样的事情。

编程是一门实践技术 213

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

并发编程9-避免活跃度危害

死锁 线程等待资源,形成一个环路就会造死锁。 数据库中事务也可能造成死锁,但是事务会自动选择一个杀死,保证另外的运行,线程可没有这么自动 锁顺序死锁 直接上代码 这种死锁,只要保持锁的顺序就不会发生 public class TestCallable { private Object left = new Object(); private Object right =

three_man的专栏 2467

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

java并发编程实践笔记五(避免活跃度危险)

目录 死锁 锁顺序死锁 动态的锁顺序死锁 协作对象间的死锁 开放调用 资源死锁 避免和诊断死锁 使用定时的锁 通过线程转储分析死锁 其他活跃度危险 饥饿 活锁 有两类线程的活跃度危险:一,锁顺序死锁:为保证安全性而不加考虑地滥用锁导致;二,资源死锁,例如我们使用线程池和信号量来约束资源的使用,在不当的使用上导致。 死锁          当线程A占有锁L时,想获得锁M...

liao_hb的专栏 492

避免活跃度危险,性能与可伸缩性(JAVA并发编程实践笔记 三)

第10章 避免活跃度危险 1. 锁顺序死锁 如果多个线程试图通过不同的顺序获得多个相同的锁,则会发生死锁。 如果所有线程以通用的固定秩序获得锁,程序就不会出现锁顺序死锁问题了。 2. 动态的锁顺序死锁 3. 协作对象间的死锁 当外部方法被调用时正持有锁,则其可能会获得其他锁(产生死锁的危险),或者遭遇严重超时的阻塞。当你持有锁的时候会延迟其他试图获得该锁的线 程。 4. 开放调...

新一天 203

《Java并发编程实战》---避免活跃性危险

在安全性和活跃性之间通常存在某种z'h

zhangbinalan的专栏 963

iOS自动化测试入门:用XCUITest实现UI测试与问题排查

在软件工程中,自动化测试是保障代码质量与交付效率的关键环节,而UI测试作为其中重要分支,专注于验证用户可见的外部行为与交互流程。针对iOS平台,苹果官方提供了XCUITest这一原生UI测试框架,它基于辅助功能树(Accessibility)实现元素定位与操作,无需额外引入第三方库即可在模拟器或真机上运行。通过模拟用户点击、输入与断言结果,XCUITest能够高效完成登录、下单等核心主流程的回归验证,弥补单元测试无法覆盖界面交互的不足。同时,合理运用等待策略、稳定标识符以及命令行工具,可以有效降低用例的偶发

weixin_34082695的博客 277

Java并发编程学习笔记(二)活跃度问题

目录 一、死锁 (一)定义 (二)锁顺序死锁 (三)协作对象间的死锁 (四)资源死锁 二、避免和诊断死锁 (一)使用显式锁 (二)通过线程转储分析死锁 三、其他活跃度问题 (一)饥饿 (二)弱响应性 (三)活锁 参考资料 在并发编程中,我们经常通过锁来保证线程安全,但使用锁也可能会带来一系列其他的问题,如死锁等问题。我们知道Java虚拟机无法从死锁中恢复,因此了解死锁的...

一颗贪婪的星 399

c++并发编程实战_看完这份Java并发编程实战pdf,再也不怕面试被问多线程与高并发...

Java提供了语言级的多线程支持,所以在Java 中使用多线程相对于在CC++当中使用多线程来说更加简单与快捷。除了Brian Goetz自己的研究、经验和热心读者的贡献之外,本书还吸取了一些并发性前沿人员的真知灼见,包括Tim Peierls. Joshua Bloch、Joseph Bowbeer、David Holmes和Doug Lea。在该书中,Brian Goetz从最基本的知识开始介...

weixin_39880899的博客 222

【*一篇足以*Java并发编程实践】《Java并发编程实践》学习Note - Part3

目录: 1.避免活跃度危险 1.1 死锁 1.2 避免和诊断死锁 1.3.其他活跃度危险 2.性能和可伸缩性 2.1 内存同步 2.2 阻塞 2.3 减少锁的竞争 3.Lock、ReentrantLock和Synchronized 3.1 可轮询和可定时的锁请求 3.1 可中断的锁获取操作 4.原子变量与非阻塞同步机制 5. JMM--Java存储模型 1.避免活跃度危...

DreamSeeker_1314的博客 329

java多线程(并发编程)

为什么要使用java的并发编程 过去的近30年间,计算机性能一直由摩尔定律来推动;从今天起,它将由Amdahl 定律推动。编写能够高效利用多处理器的代码,将会成为很大的挑战。 “多核处理器正变得越来越便 宜”。现在看来,多处理器系统正变得越来越便宜这一趋势 还在继续,如果有什么不同,只是愈演愈烈了。几乎所有主要的计算机生产厂商都在初级 笔记本电脑和台式机中加入了多核处理器特性,而在服务器级别的机器上,每个处理器的 内核数量也多于去年的内核数量。事实上,寻找出单处理器的系统正...

qq_36448587的博客 260

《JAVA并发编程实践》学习笔记(第十.十一章)

第10章 避免活跃度危险 10.1 死锁        当一个线程永远占有一个锁,而其他线程尝试去获得这个锁,那么它们将永远被阻塞。        与其他并发危险相同,死锁很少被立即发现。一个类如果有发生死锁的潜在可能并不意味着死锁每次都发生,它只发生在改发生的时候。当死锁出现的时候,往往是最不幸的时候——在高负载之下。 10.1.1 锁顺序死锁        如果所有线程一通用的固定秩

GS_008的专栏 591

java并发编程实践学习(10)死锁

安全性和活跃度通常相互制约。我们使用锁来保证线程安全,但是滥用锁可能引起锁顺序死锁。一.死锁当一个线程永远占有一个锁,而其他线程尝试去获得这个锁,那么他们将永远阻塞。当线程A占有锁L时,想要获得锁M,但是同时线程B持有M,尝试获得L,俩个线程将永远等待下去这被称作死锁(或称致命拥抱)。

memoryCoderC的博客 405
上一篇: 并发编程原则与技术(四)——组合对象
下一篇: 迁移Oracle数据的两个方案(待续)
javacoffe
博客等级 码龄19年 147粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值