码迷,mamicode.com
首页 > 编程语言 > 详细

并发编程的挑战(Java并发编程的艺术)

时间:2020-02-13 00:20:41      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:lis   资源   wait   exce   cas   sync   add   共享资源   协程   

1.上下文切换
CPU通过给每个线程分配CPU时间片来实现并发,切换过程中线程的信息从保存到再加载就是一个上下文切换。由于频繁的进行上下文切换,会消耗资源,所以并发不一定比串行快。

可以通过Lmbench3测量上下文切换的时长;可以通过vmstat测量上下文切换的次数。

减少上下文切换的方法:

(1)无锁并发编程,例如通过ThreadLocal,不变模式等;

(2)CAS算法;

(3)使用最小的线程;

(4)协程

2.死锁
有个叫 Coffman 的牛人早就总结过了,只有以下这四个条件都发生时才会出现死锁:

(1)互斥,共享资源 X 和 Y 只能被一个线程占用;

(2)占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;

(3)不可抢占,其他线程不能强行抢占线程 T1 占有的资源;

(4)循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。

避免死锁的方法:

(1)避免一个线程同时获取多个锁;

(2)避免一个线程在锁内同时占用多个资源,尽量一个锁一个资源;

(3)尝试使用定时锁,使用lock.tryLock(timeout)代替内部锁机制;

(4)对于数据库锁,加锁和解锁必须在一个数据库连接里面,否则会出现解锁是吧;

(5)如果必须使用锁锁住多个资源,例如转账,需要一次锁住转账账户、收款账户,可以用一定规则顺序锁定资源,即根据账户ID从小到大的规则,依次锁定账户,则可避免死锁;另外可以写个单例类来实现锁资源的申请、释放,代码示例如下:

class Allocator {

private List als;

// 一次性申请所有资源

synchronized void apply(

Object from, Object to){

// 经典写法

while(als.contains(from) ||

    als.contains(to)){

  try{

    wait();

  }catch(Exception e){

  } 

}

als.add(from);

als.add(to); 

}

// 归还资源

synchronized void free(

Object from, Object to){

als.remove(from);

als.remove(to);

notifyAll();

}

}

并发编程的挑战(Java并发编程的艺术)

标签:lis   资源   wait   exce   cas   sync   add   共享资源   协程   

原文地址:https://www.cnblogs.com/Johar/p/12301741.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!