多线程系列三:Lock和Condition
有了synchronized为什么还要Lock?
因为Lock和synchronized比较有如下优点
1、 尝试非阻塞地获取锁
2、 获取锁的过程可以被中断
3、 超时获取锁
Lock的标准用法
package com.lgs; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* 显示锁lock的标准写法
*/
public class LockTemplete { public static void main(String[] args) {
Lock lock = new ReentrantLock();
//获取锁
lock.lock();
try{
// do my work.....
}finally{
//释放锁
lock.unlock();
}
} }
Lock的常用方法
Lock() 获取锁
tryLock尝试非阻塞地获取锁
lockInterruptibly:获取锁的过程可以被中断
tryLock(long time, TimeUnit unit) 超时获取锁
unlock()释放锁
锁的可重入
一个线程获得了锁进入了同步代码块遇到了锁仍然可以进入同步代码块
递归的时候发生锁的重入,没有锁的可重入,就会死锁
公平和非公平锁
公平锁,先对锁发出获取请求的一定先被满足。公平锁的效率比非公平锁效率要低。
为什么非公平锁的性能要高:因为非公平锁是可以插队的,如线程C被唤醒变为可执行去获取锁的过程中,线程A插队进来直接获取锁执行自己的业务,线程A执行完以后,线程C刚好唤醒完直接就获取锁运行了,这样在线程C唤醒的过程中线程A就执行完了效率更高
读写锁ReentrantReadWriteLock
允许多个读线程同时进行,但是只允许一个写线程(不允许其他读线程防止脏读和写线程),支持读多写少场景,性能会有提升。
package com.lgs; import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* lgs
* 读写锁的使用
*/
public class RwLockTemplete { static final Map<String,String> map = new HashMap<>();
static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
static Lock r = reentrantReadWriteLock.readLock();
static Lock w = reentrantReadWriteLock.writeLock(); public void put(){
w.lock();
try{
// do my work.....
}finally{
w.unlock();
}
} public void get(){
r.lock();
try{
// do my work.....
}finally{
r.unlock();
}
} }
Condition接口有何用处?
Object的 wait,notify/notifyAll 实现等待通知机制
Condition接口和Lock配合来实现等待通知机制
Condition常用方法和使用范式
package com.lgs; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* Condition的使用方式
*/
public class ConditionTemplete { Lock lock = new ReentrantLock();
Condition condition = lock.newCondition(); public void waitc() throws InterruptedException {
lock.lock();
try{
condition.await();
}finally{
lock.unlock();
}
} public void waitnotify() throws InterruptedException {
lock.lock();
try{
condition.signal();
//condition.signalAll();尽量少使用
}finally{
lock.unlock();
}
} }
结合ReentrantLock和Condition实现线程安全的有界队列
package com.lgs.bq; import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* lgs
* 结合ReentrantLock和Condition实现线程安全的有界队列
*/
public class BlockingQueueLC<T> {
private List queue = new LinkedList<>();
private final int limit;
Lock lock = new ReentrantLock();
private Condition needNotEmpty = lock.newCondition();
private Condition needNotFull = lock.newCondition(); public BlockingQueueLC(int limit) {
this.limit = limit;
} public void enqueue(T item) throws InterruptedException {
lock.lock();
try{
while(this.queue.size()==this.limit){
needNotFull.await();
}
this.queue.add(item);
//通知出队线程有数据可以取了
needNotEmpty.signal();
}finally{
lock.unlock();
}
} public T dequeue() throws InterruptedException {
lock.lock();
try{
while(this.queue.size()==0){
needNotEmpty.await();
}
//通知入队线程有位置可以入队了
needNotFull.signal();
return (T) this.queue.remove(0);
}finally{
lock.unlock();
}
}
}
package com.lgs.bq; /**
*
*/
public class BqTest {
public static void main(String[] args) {
BlockingQueueLC<Integer> bq = new BlockingQueueLC(10);
Thread threadA = new ThreadPush(bq);
threadA.setName("Push");
Thread threadB = new ThreadPop(bq);
threadB.setName("Pop");
threadB.start();
threadA.start();
} private static class ThreadPush extends Thread{
BlockingQueueLC<Integer> bq; public ThreadPush(BlockingQueueLC<Integer> bq) {
this.bq = bq;
} @Override
public void run() {
String threadName = Thread.currentThread().getName();
int i = 5;
while(i>0){
try {
Thread.sleep(500);
System.out.println(" i="+i+" will push");
bq.enqueue(i--);
} catch (InterruptedException e) {
//e.printStackTrace();
} }
}
} private static class ThreadPop extends Thread{
BlockingQueueLC<Integer> bq; public ThreadPop(BlockingQueueLC<Integer> bq) {
this.bq = bq;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+" will pop.....");
Integer i = bq.dequeue();
System.out.println(" i="+i.intValue()+" alread pop");
} catch (InterruptedException e) {
//e.printStackTrace();
}
} }
}
}
多线程系列三:Lock和Condition的更多相关文章
- java多线程系列(四)---Lock的使用
Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- (Java多线程系列三)线程间通讯
Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- 【Java多线程系列三】实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式的加锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- Java多线程系列 JUC锁06 Condition条件
Condition介绍 Condition中提供了一组类似于Object中的监视器方法.与Lock配合可以完成等待通知模式. Lock lock = new ReentrantLock(); Cond ...
- Java多线程系列十——BlockingQueue
参考资料:http://ifeve.com/java-synchronousqueue/http://www.cnblogs.com/jackyuj/archive/2010/11/24/188655 ...
- java并发编程系列三、Lock和Condition
有了synchronized为什么还要Lock? 因为Lock和synchronized比较有如下优点 1. 尝试非阻塞地获取锁 2. 获取锁的过程可以被中断 3. 超时获取锁 Lock的标准用法 p ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
随机推荐
- linux怎么关闭iptables linux如何关闭防火墙
Linux系统下面自带了防火墙iptables,iptables可以设置很多安全规则.但是如果配置错误很容易导致各种网络问题,那么如果要关闭禁用防火墙怎么操作呢,咗嚛本经验以centos系统为例演示如 ...
- ES6,新增数据结构Set的用法
ES6 提供了新的数据结构 Set. 特性 似于数组,但它的一大特性就是所有元素都是唯一的,没有重复. 我们可以利用这一唯一特性进行数组的去重工作. 单一数组的去重. let set6 = new S ...
- 【Linux】crontab 定时启动sh
crontab -e 20点59分启动脚本 59 20 * * * sh /home/fzuir/xingye4crawl/endXingYe4Crawl.sh >/home/fzuir/xin ...
- C语言字符串格式化显示
符号 作用 ────────────────────────── %d 十进制有符号整数 %i 输 ...
- poj3073
比赛状态堪忧,笑看自己找不着北.. 把心态放好吧- - 反正窝从一開始就仅仅是为了多学习才上道的 至少已经从学习和智商上给窝带来了一些帮助 智商带不动,好辛苦----(>_<)---- 说 ...
- js+jquery检测用户浏览器型号(转)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C语言 · 学做菜
算法训练 学做菜 时间限制:1.0s 内存限制:256.0MB 问题描述 涛涛立志要做新好青年,他最近在学做菜.由于技术还很生疏,他只会用鸡蛋,西红柿,鸡丁,辣酱这四种原料来做菜,我 ...
- strace命令用法详解
Linux利器 strace strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必 ...
- Redis的内存回收机制
Redis的内存回收机制 2018年01月16日 17:11:48 chs007chs 阅读数:1172 Redis的内存回收机制主要体现在一下两个方面: 删除过期时间的键对象 删除过期键对象 : ...
- git基本操作:上传代码
利用git将本地代码提交到远程服务器一般分为如下5个步骤: 一.查看当前文件的状态 使用git status命令可以查看有那些文件进行了修改,一般有下面几个状态: 1.Untracked: 未跟踪, ...