频道栏目
首页 > 程序开发 > 软件开发 > Java > 正文
Java Lock与Condition的理解 ReentrantLock锁的简单使用技巧
2018-06-13 11:31:48      个评论    来源:zengrenyuan的专栏  
收藏   我要投稿

Lock

ReentrantLock 是我们常用的锁,日常我们都只使用了其中一部分功能如下:

  ReentrantLock lock = new ReentrantLock();
  lock.lock();
  try {
.... 
  } finally {
lock.unlock();
  }

实际上Java提供的LinkedBlockingQueue类就是基于ReentrantLock与Condition结合使用的,这是很经典的生产与消费场景,里面有两个锁putLock与takeLock锁。解决问题:取元素时takeLock已经获取到锁了,但是由于列队是空的,使用notEmpty.await()使当前线程处理等待状态,这时如果有新的线程调用take方法时,新的线程也能获取到锁,也会继续等待,当put元素后, notEmpty.signal()发送信号,会唤醒其中一个等待线程。
使用condition可以使线程交互变的更加灵活,ReentrantLock可以定义公平锁与非公平锁,公平锁可以保证线程访问顺序,非公平锁不一定保证线程访问顺序,默认为非公平锁。

take方法

//每次取完之后使用自唤醒方法使其它等待线程,多了一重信息通知,取完之后会调用notFull方法唤醒正在等写入的方法
public E take() throws InterruptedException {
  E x;
  int c = -1;
  final AtomicInteger count = this.count;
  final ReentrantLock takeLock = this.takeLock;
  takeLock.lockInterruptibly();//获取锁
  try {
while (count.get() == 0) {//如果当前元素为0线程等待
 notEmpty.await();
}
x = dequeue();//取一个元素
c = count.getAndDecrement();//总数减1
if (c > 1)//如果有元素 继续唤醒一个等待线程
 notEmpty.signal();
  } finally {
takeLock.unlock();
  }
  if (c == capacity)
signalNotFull();
  return x;
 }

put方法

public void put(E e) throws InterruptedException {
 if (e == null) throw new NullPointerException();
 int c = -1;
 Node node = new Node(e);
 final ReentrantLock putLock = this.putLock;
 final AtomicInteger count = this.count;
 putLock.lockInterruptibly();
 try { 
  while (count.get() == capacity) {//列队满,等列队有空间
notFull.await();
  }
  enqueue(node);//插入元素
  c = count.getAndIncrement();//总数加1
  if (c + 1 < capacity)//列队未满,唤醒正在等待的线程
notFull.signal();
 } finally {
  putLock.unlock();
 }
 if (c == 0)//通知正在等待取元素的线程
  signalNotEmpty();
}

synchronized锁

synchronized (writeLock) {
 while (runThreadNum >= 5) {
  try {
System.out.println("threadNum:" + runThreadNum);
writeLock.wait();
  } catch (InterruptedException e) {
e.printStackTrace();
  }
 }
}

测试代码实例

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by zengrenyuan on 18/6/11.
 */
public class TestLock {

 public static final int maxNum = 1;
 private final ReentrantLock lock = new ReentrantLock();
 private final Condition notFull = lock.newCondition();
 private final Condition notEmpty = lock.newCondition();
 private AtomicInteger count = new AtomicInteger(0);

 public static void main(String[] args) throws InterruptedException {
  final TestLock testLock = new TestLock();
  testLock.putThread("线程1");
  testLock.putThread("线程2");
  testLock.putThread("线程3");
  testLock.putThread("线程4");
  testLock.putThread("线程5");
  testLock.readThread("读线程");
 }

 public void readThread(String name) {
  Thread thread = new Thread(new Runnable() {
@Override
public void run() {
 while (true) {
  try {
read();
  } catch (InterruptedException e) {
e.printStackTrace();
  }
 }
}
  });
  thread.setName(name);
  thread.start();


 }

 public void read() throws InterruptedException {
  lock.lock();
  try {
while (count.get() == 0) {
 notEmpty.await();
}
System.out.println("read:" + count.decrementAndGet());
notFull.signal();
  } finally {
lock.unlock();
  }
 }


 public void putThread(String name) {
  Thread thread = new Thread(new Runnable() {
@Override
public void run() {
 try {
  print();
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
}
  });
  thread.setName(name);
  thread.start();
 }

 public void print() throws InterruptedException {
  lock.lock();
  try {
System.out.println("threadName" + Thread.currentThread().getName());
while (count.get() == maxNum) {
 notFull.await();
}
System.out.println("put:" + count.getAndIncrement() + " threadName" + Thread.currentThread().getName());
System.out.println(MiscUtils.formatDate(new Date(), MiscUtils.STANDARDPATTERN));
notEmpty.signal();
  } finally {
lock.unlock();
  }
 }
}
点击复制链接 与好友分享!回本站首页
上一篇:Java开发设计模式之装饰模式解析
下一篇:最后一页
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站