有了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();
}
} }
}
}

java并发编程系列三、Lock和Condition的更多相关文章

  1. Java并发编程系列-(5) Java并发容器

    5 并发容器 5.1 Hashtable.HashMap.TreeMap.HashSet.LinkedHashMap 在介绍并发容器之前,先分析下普通的容器,以及相应的实现,方便后续的对比. Hash ...

  2. Java并发编程系列-(4) 显式锁与AQS

    4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关 ...

  3. Java并发编程系列-(1) 并发编程基础

    1.并发编程基础 1.1 基本概念 CPU核心与线程数关系 Java中通过多线程的手段来实现并发,对于单处理器机器上来讲,宏观上的多线程并行执行是通过CPU的调度来实现的,微观上CPU在某个时刻只会运 ...

  4. 干货:Java并发编程系列之volatile(二)

    接上一篇<Java并发编程系列之synchronized(一)>,这是第二篇,说的是关于并发编程的volatile元素. Java语言规范第三版中对volatile的定义如下:Java编程 ...

  5. Java并发编程系列-(6) Java线程池

    6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...

  6. Java并发编程系列-(7) Java线程安全

    7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...

  7. Java并发编程系列-(8) JMM和底层实现原理

    8. JMM和底层实现原理 8.1 线程间的通信与同步 线程之间的通信 线程的通信是指线程之间以何种机制来交换信息.在编程中,线程之间的通信机制有两种,共享内存和消息传递. 在共享内存的并发模型里,线 ...

  8. 原创】Java并发编程系列2:线程概念与基础操作

    [原创]Java并发编程系列2:线程概念与基础操作 伟大的理想只有经过忘我的斗争和牺牲才能胜利实现. 本篇为[Dali王的技术博客]Java并发编程系列第二篇,讲讲有关线程的那些事儿.主要内容是如下这 ...

  9. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

随机推荐

  1. scrapy-redis爬取豆瓣电影短评,使用词云wordcloud展示

    1.数据是使用scrapy-redis爬取的,存放在redis里面,爬取的是最近大热电影<海王> 2.使用了jieba中文分词解析库 3.使用了停用词stopwords,过滤掉一些无意义的 ...

  2. Java逐行写入字符串到文件

    下边是写东西到一个文件中的Java代码.运行后每一次,一个新的文件被创建,并且之前一个也将会被新的文件替代.这和给文件追加内容是不同的. 1. public static void writeFile ...

  3. mac 上传下载iterm2

    1.安装Homebrew,目的是执行 brew 命令,解决 brew: command not found问题 ruby -e "$(curl -fsSL https://raw.githu ...

  4. R语言 画图roc

    这才是我要的滑板鞋~~~~~ #glm模型glm.model=train(y~.,data=data_train, method="glm", metric="ROC&q ...

  5. 跨平台设置NODE_ENV(兼容win和linux)

    通过NODE_ENV可以来设置环境变量(默认值为development).一般我们通过检查这个值来分别对开发环境和生产环境下做不同的处理.可以在命令行中通过下面的方式设置这个值: linux & ...

  6. python 压缩文件为zip后删除原文件

    压缩.log 文件为zip后删除原文件 需要注意:本人作为小白,该脚本需要和.log在一起,后面有时间需要改正. #!/usr/local/python/bin/python #-*-coding=u ...

  7. myisamchk命令修复表操作

    myisamchk命令使用总结 myisamchk实用程序可以用来获得有关你的数据库表的统计信息或检查.修复.优化他们 1.常用于myisamchk的检查选项--information, -i打印所检 ...

  8. 学习windows编程 day4 之 映射模式

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...

  9. 利用@jsonView注解来实现自定义返回字段

    业务场景:比如说一个User对象,有两个字段,一个username,一个password,有一个获取用户信息的接口要返回这个User列表,但是不想要这个User列表的password字段. 还有一个接 ...

  10. Hbase记录-client访问zookeeper大量断开以及参数调优分析(转载)

    1.hbase client配置参数 超时时间.重试次数.重试时间间隔的配置也比较重要,因为默认的配置的值都较大,如果出现hbase集群或者RegionServer以及ZK关掉,则对应用程序是灾难性的 ...