JAVA语言 Lock与Condition的理解 ReentrantLock锁的简单使用技巧
小标 2018-12-04 来源 : 阅读 654 评论 0

摘要:本文主要向大家介绍了JAVA语言 Lock与Condition的理解 ReentrantLock锁的简单使用技巧,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言  Lock与Condition的理解 ReentrantLock锁的简单使用技巧,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


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<e> node = new Node<e>(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();

}</e></e>

   


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));

<code class="java pla    

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程