Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java并发编程的艺术笔记第五章——java中的锁

java并发编程的艺术笔记第五章——java中的锁

作者头像
会跳舞的机器人
发布于 2018-09-21 08:15:57
发布于 2018-09-21 08:15:57
43700
代码可运行
举报
运行总次数:0
代码可运行

1、Lock接口

锁是用来控制多个线程访问共享资源的方式,一般来说锁能够防止多个线程同时访问共享资源(有的锁可以允许多个线程访问共享资源,比如说读写锁),在Lock接口出现之前,java程序是靠synchronized关键字实现锁功能的,但是在JKD1.5之后并发包中新增了Lock接口及其实现来实现锁的功能。它提供了synchronized关键字类似的功能,但是Lock需要显示的获取锁、释放锁,而synchronized是通过隐式的方式来实现获取、释放锁。

Lock接口常见的API请自行查找

2、队列同步器

略…

3、重入锁

重入锁ReentrantLock,顾名思义,就是支持重进入的锁,重入锁支持同一个线程多次的获取锁。除此之外,该锁还支持获取锁时的公平和非公平性。

关于锁的公平性,如果在绝对的时间上,先对锁进行获取请求的操作一定会先被满足,则说明这个锁是公平的,反之则是不公平的。ReentrantLock的构造函数支持构造公平锁与非公平锁,默认为非公平锁,因为非公平锁能减少上下文切换,开销更小。

4、读写锁

读写锁支持同一时刻允许多个线程同时访问,但是在写线程访问时,所有的读线程与其他的写线程均被阻塞。读写锁维护了一对锁,读锁与写锁,通过读锁与写锁的分离,读写锁的并发性相比于其他排他锁都有很大的提升。

java并发包提供的读写锁是ReentrantReadWriteLock,它具有公平性选择、锁重入、锁降级三个特性。

读写锁实现简单缓存demo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main.java.com.robot.demo;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author: 会跳舞的机器人
 * @date: 2017/8/16 14:45
 * @description: 读写锁实现缓存demo
 */
public class Cache {
    static Map<String, Object> map = new HashMap<>();
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    static Lock writeLock = rwl.writeLock();
    static Lock readLock = rwl.readLock();

    /**
     * 读缓存
     */
    public static final Object get(String key) {
        readLock.lock();
        try {
            return map.get(key);
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 写入缓存
     */
    public static final Object put(String key, Object value) {
        writeLock.lock();
        try {
            return map.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 清空缓存
     */
    public static final void clear() {
        writeLock.lock();
        try {
            map.clear();
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 获取缓存大小
     */
    public static final int size() {
        writeLock.lock();
        try {
            return map.size();
        } finally {
            writeLock.unlock();
        }
    }
}

5、LockSupport工具

略…

6、Condition接口

利用Condition接口来实现一个简单的有界阻塞队列,当队列为空时,队列的获取操作将会阻塞获取线程,知道有新的元素添加进来,当队列满时,队列的插入操作将会阻塞插入线程,知道队列出现“空位”。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main.java.com.robot.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: 会跳舞的机器人
 * @date: 2017/8/16 15:48
 * @description: Condition实现有界阻塞队列demo
 */
public class BoundedQueue {
    private Object[] items;

    private int addIndex, removeIndex, count;

    private Lock lock = new ReentrantLock();

    private Condition notEmpty = lock.newCondition();

    private Condition notFull = lock.newCondition();

    public BoundedQueue(int size) {
        items = new Object[size];
    }

    /**
     * 添加一个元素,如果队列已满,则线程进入等待状态,直到有空位为止
     */
    public void add(Object object) throws InterruptedException {
        lock.lock();
        try {
            // 队列已满,阻塞线程
            while (items.length == count) {
                System.out.println("队列已满,等待......");
                notFull.await();
            }
            items[addIndex] = object;
            if (++addIndex == items.length) {
                addIndex = 0;
            }
            ++count;
            // 唤醒
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 删除队列的第一个元素,如果队列为空,则线程进入等待状态,直到有新元素添加进来
     */
    public Object remove() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                System.out.println("空队列,等待......");
                notEmpty.await();
            }
            Object obj = items[removeIndex];
            if (++removeIndex == items.length) {
                removeIndex = 0;
            }
            --count;
            notFull.signal();
            return obj;
        } finally {
            lock.unlock();
        }
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java中Locks的使用
之前文章中我们讲到,java中实现同步的方式是使用synchronized block。在java 5中,Locks被引入了,来提供更加灵活的同步控制。
程序那些事
2020/07/08
5060
JUC系列(八)| 读写锁-ReadWriteLock
我们开发中应该能够遇到这样的一种情况,对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是当一个写者线程在写这些共享资源时,就不允许其他线程进行访问。
宁在春
2022/10/31
3730
JUC系列(八)| 读写锁-ReadWriteLock
Java的独占锁和共享锁
昨天了不起带着大家一起学习了关于这个乐观锁,悲观锁,递归锁以及读写锁,今天我们再来看看这个关于 Java 的其他的锁,大家都了解 Java 的锁有很多种,我们今天再来介绍四种锁。
Java极客技术
2024/01/31
3350
Java的独占锁和共享锁
面试官:说说读写锁的实现原理?
在实际项目开发中,并发编程一定会用(提升程序的执行效率),而用到并发编程那么锁机制就一定会用,因为锁是保证并发编程的主要手段。
磊哥
2024/08/12
3790
Java并发编程:同步锁、读写锁
之前我们说过线程安全问题可以用锁机制来解决,即线程必要要先获得锁,之后才能进行其他操作。其实在 Java 的 API 中有这样一些锁类可以提供给我们使用,与其他对象作为锁相比,它们具有更强大的功能。 Java 中的锁有两种,分别是:1)同步锁 2)读写锁 一、同步锁   同步锁(ReentrantLock)类似于 synchronize 代码块中传入的那个锁对象,可以用于进行线程同步。ReentrantLock.lock() 方法用于锁定对象,而 ReentrantLock.unlock 用于释放锁对象。
陈树义
2018/04/13
1.2K0
Java中的锁的使用和实现介绍
锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。 源代码基于 1.8.0
用户7886150
2020/12/04
5770
并发编程系列之ReadWriteLock使用
ReadWriteLock是jdk的juc包中提供的读写锁api,维护一对关联的读锁、写锁,读锁可以被多个读线程共享,写锁排他。
SmileNicky
2021/12/04
6890
并发编程系列之ReadWriteLock使用
死磕 java同步系列之ReentrantReadWriteLock源码解析
(4)如何使用ReentrantReadWriteLock实现高效安全的TreeMap?
彤哥
2019/07/08
3610
死磕 java同步系列之ReentrantReadWriteLock源码解析
java并发编程实战(3) Lock显示锁
  synchronized是java中的一个关键字,也就是说是Java语言内置的特性。那么为什么会出现Lock呢?
黄规速
2022/04/14
3910
java并发编程实战(3)  Lock显示锁
java开发中几种常见的线程池
线程池 java.util.concurrent:Class Executors 常用线程池 几种常用的的生成线程池的方法: newCachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor newSingleThreadScheduledExecutor 例子:newFixedThreadPool ExecutorService threadPool = Executors.newFixe
xiangzhihong
2018/02/01
8970
《Java-SE-第二十七章》之常见的锁策略
 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
用户10517932
2023/10/07
1840
《Java-SE-第二十七章》之常见的锁策略
字节面试:说说Java中的锁机制?
Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。
磊哥
2024/05/13
1650
字节面试:说说Java中的锁机制?
高并发之——浅谈AQS中的Lock与Condition
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
冰河
2020/10/29
5510
【并发编程】可重入锁和读写锁
一般使用lock.lock();就try catch 在finally里释放锁:lock.unlock(); 功能和synchronized差不多 比synchronized轻量
周杰伦本人
2022/10/25
3400
【并发编程】可重入锁和读写锁
Java并发-显式锁篇【可重入锁+读写锁】
这也是为啥默认是非公平锁的原因(一般情况下,非公平锁的性能高于公平锁) 那什么时候应该用公平锁呢?
汤圆学Java
2021/05/23
5620
Java Review - 并发编程_读写锁ReentrantReadWriteLock的原理&源码剖析
解决线程安全问题使用ReentrantLock就可以,但是ReentrantLock是独占锁,某时只有一个线程可以获取该锁,而实际中会有写少读多的场景,显然ReentrantLock满足不了这个需求,所以ReentrantReadWriteLock应运而生。ReentrantReadWriteLock采用读写分离的策略,允许多个线程可以同时获取读锁。
小小工匠
2021/12/05
2850
Java Review - 并发编程_读写锁ReentrantReadWriteLock的原理&源码剖析
深夜!小胖问我什么是读写锁?插队策略?升降级?
来到多线程的第十二篇,前十一篇请点文末底部的上、下一篇标签。这篇聊聊读写锁。什么是读锁 & 写锁?开篇之前先聊聊这小两口的定义:
JavaFish
2021/01/05
1.4K0
Java并发编程实战系列13之显式锁 (Explicit Locks)
Java5之前只能用synchronized和volatile,5后Doug Lea加入了ReentrantLock,并不是替代内置锁,而是当内置锁机制不适用时,作为一种可选择的高级功能 不适用包括
JavaEdge
2018/04/28
1.1K0
Java并发编程实战系列13之显式锁 (Explicit Locks)
Java多线程,对锁机制的进一步分析
可重入锁,也叫递归锁。它有两层含义,第一,当一个线程在外层函数得到可重入锁后,能直接递归地调用该函数,第二,同一线程在外层函数获得可重入锁后,内层函数可以直接获取该锁对应其它代码的控制权。之前我们提到的synchronized和ReentrantLock都是可重入锁。
用户1153489
2020/02/18
5040
【原创】Java并发编程系列17 | 读写锁八讲(上)
通过以下几部分来分析Java提供的读写锁ReentrantReadWriteLock:
java进阶架构师
2020/04/07
5810
【原创】Java并发编程系列17 | 读写锁八讲(上)
相关推荐
java中Locks的使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验