JDK6中LinkedBlockingQueue中的锁机制

常识,之前有的没搞清楚,导致写代码时不少疑惑。

比较典型的同步例子,用了两个Condition,notEmpty和notFull,分别对应两个lock,takeLock和putLock。查看take的代码:

E x;

int c = -1;

final AtomicInteger count = this.count;

final AtomicInteger takeLock = this.takeLock;

takeLock.lockInterruptibly();

try {

  try {

    while (count.get() == 0) notEmpty.await();

  } catch (InterruptedException ie) {

    notEmpty.signal();

    throw ie;

  }

  x = extract();

  c = count.getAndDecrement();

  if (c > 1) {

    notEmpty.signal();

  }

} finally {

  takeLock.unlock();

}

if (c == capacity) {

  signalNotFull();

}

return x;

singalNotFull中代码:

putLock.lock();

try { notFull.signal(); } finally { putLock.unlock(); }

可以看出:

1.take操作可能会block,应允许终端,所以用lockInterruptably更友好

2.for循环await是java文档推荐的,await成功不代表条件满足,这种唤醒称为伪唤醒(spurious wakeup)

3.await()抛出InterruptedException后signal让下一个等待线程伪唤醒

4.用signal而不是signalAll,一次只唤醒一个线程,取完之后发现还有就再signal,唤醒下一个等待线程,这是因为condition可用时不一定能让所有take线程获取成功(看队列当前size够不够),因而不必signalAll

5.使用了两把锁,take时notEmpty(lock await)=>notFull(lock signal),put时:notFull(lock await) => notEmpty(lock signal),因此take和put可以兵法,另外有个问题是put在notFull lock后进入await,block住了,take线程会不会拿不到notFull的锁signal而导致死锁呢?答案是不会,因为await会先释放掉锁然后在返回钱重新获得锁。其实object的wait也有相同特性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值