java并发编程实践(4)

1、扩展ThreadPoolExecutor该类中的beforeExcute(任务执行前被调用)、afterExecute(任务执行后被调用,无论是否正常被执行,抛出异常也会被执行)、terminated(线程池完成关闭时执行)方法可在子类中被改写;
2、锁顺序死锁:多个线程以不同的顺序获得多个对象的锁时发生死锁的现象;eg:

/*线程1:*/
synchronized(obj1){
    synchronized(obj2){
    /*语句块*/
    }
}
/*线程2:*/
synchronized(obj2){
    synchronized(obj1){
    /*语句块*/
    }
}

此时如果线程1获得obj1的锁而线程2 获得obj2的锁,那么会形成死锁;
如果以相同的顺序获取锁,死锁问题就能得到解决:

/*线程1:*/
synchronized(obj1){
    synchronized(obj2){
    /*语句块*/
    }
}
/*线程2:*/
synchronized(obj1){
    synchronized(obj2){
    /*语句块*/
    }
}

3、开放调用
如果调用某个方法时不需要持有锁,这种方式称作开放调用;

/*协作对象之间产生死锁**/
class A {
   private B b = new B();
   public synchronized void a(){
       /*需要同步的重要代码*/
        b.b();
   }
   public synchronized void c(){
   }
}
class B{
   private A a = new A();
   public synchronized b(){
   }
   pubic synchronized d(){
        /*需要同步的重要代码*/
        a.c();
   }
}

如果对象之间存在协作,当线程1调用class B的d()方法时,此时线程1可能获得两个锁,如果线程2调用class A的a()方法,此时线程2也有可能获得两个锁,当且仅当线程1没获得锁时这个可能性才成立,若线程1获得class B的锁而线程2获得class A的锁,那么此时会发生死锁现象;
采用开放调用的方式可以解决这个问题:

/*开放调用**/
class A {
   private B b = new B();
   public void a(){
        synchronized(this){
          /*需要同步的重要代码*/
        }
        b.b();
   }
   public synchronized void c(){
   }
}
class B{
   private A a = new A();
   public synchronized b(){
   }
   pubic  d(){
       synchronized(this){
          /*需要同步的重要代码*/
        }
        a.c();
   }
}

此时调用外部方法时,线程已经没有持有锁,因此不会发生死锁的现象。
4、减小锁的竞争
1)、减小锁的范围(”快进快出”),比如如果采用synchronized关键字修饰整个方法,资源就被线程独占,若方法体执行时间长,影响整个程序的性能,若果我们将方法中需要同步的代码用synchronized同步,则可能能减少线程对当前资源的持有时间;
2)、减小锁的粒度
ArrayBlockingQueue不支持同时读写,其底层实现使用了ReextranLock锁,类似synchronized方法会被调用线程独占,而LinkedBlockingQueue减小了锁的粒度,其实现对读操作和写操作分别用了不同的锁,所以可以同时读写操作

public class LinkedBlockingQueue<T>{
      Lock write = new ReextranceLock();
      Lock read= new ReextranceLock();
      /*读操作*/
      public T take(){
       write.lock();
       /**其他代码省略**/
      }
      /*写操作*/
      public void put(T e){
       read.lock();
       /**其他代码省略**/
      }
}

3)、锁分段
将锁使用在一组独立的对象上,如ConcurrentHashMap;其使用的是散列数据结构,每个桶位独占一把锁,因此可以支持多线程并发访问;其伪代码如下:

public class ConncurrentHashMapTest{
 private static final INI_LOCK = 16;
 private final Node[] bucket;
 private final Object[] lock;
 private static Node{
    /*省略*/
 }
 public Object get(Object key){
   int i = hash(key);
   synchronized(lock[i]){
        /*省略*/
   }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值