JUC同步锁(五)
根据锁的添加到Java中的时间,Java中的锁,可以分为“同步锁”和“JUC包中的锁”。
一、同步锁--synchronized关键字
通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。
同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!
二、JUC包中的锁
相比同步锁,JUC包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。Lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区,相对于synchronized,Lock接口及其实现类提供了更加强大、灵活的锁机制。
JUC包中的锁,包括:
- Lock接口
- ReadWriteLock接口
- Condition接口
- ReentrantLock独占锁
- ReentrantReadWriteLock读写锁
- CountDownLatch
- CyclicBarrier
- Semaphore
- AbstractOwnableSynchronizer抽象类
- AbstractQueuedSynchronizer抽象类
- AbstractQueuedLongSynchronizer抽象类
下面以简单的实例对两种锁进行介绍:
(1)简单的锁synchronized:
public class ThreadTest {
    public void test(){
        synchronized(this){
            //do something
        }
    }
}
(2)lock锁实现
public class ThreadTest {
    Lock lock = new Lock();
    public void test(){
        // 当前线程会被阻塞,直到该Lock对象的unlock()方法被调用
        lock.lock();
        //do something
        // 释放锁
        lock.unlock();
    }
}
lock()方法会对Lock实例对象进行加锁,因此所有对该对象调用lock()方法的线程都会被阻塞,直到该Lock对象的unlock()方法被调用。
Lock锁实现:
public final synchronized void lock() throws InterruptedException{
    // 当isLocked为true时,调用lock()的线程在wait()调用上阻塞等待。
    while(this.locked) {
        this.wait();
    }
	// 让其它正在调用lock()方法的线程能够在Lock实例上加锁。
    this.locked = true;
}
public final synchronized void unlock() {
    this.locked = false;
    this.notifyAll();
}
 当isLocked为true时,调用lock()的线程在wait()调用上阻塞等待。为防止该线程没有收到notify()调用也从wait()中返回,这个线程会重新去检查isLocked条件以决定当前是否可以安全地继续执行还是需要重新保持等待,而不是认为线程被唤醒了就可以安全地继续执行了。如果isLocked为false,当前线程会退出while(isLocked)循环,并将isLocked设回true,让其它正在调用lock()方法的线程能够在Lock实例上加锁。
三、详解JUC包中的各个锁
锁的框架图如下:

(1)Lock 接口
Lock为接口类型,Lock实现提供了比使synchronized方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的Condition对象。
JUC 包中的 Lock 接口支持那些语义不同 (重入、公平等) 的锁规则。所谓语义不同,是指锁可是有 “公平机制的锁”、”非公平机制的锁”、”可重入的锁” 等等。”公平机制” 是指 “不同线程获取锁的机制是公平的”,而 “非公平机制” 则是指 “不同线程获取锁的机制是非公平的”,”可重入的锁” 是指同一个锁能够被一个线程多次获取。
(2)ReadWriteLock
 ReadWriteLock为接口类型, 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。
 ReadWriteLock 接口以和 Lock 类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC 包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
(3)Condition
 Condition为接口类型,它将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。可以通过await(),signal()来休眠/唤醒线程。
 Condition 需要和 Lock 联合使用,它的作用是代替 Object 监视器方法,可以通过 await(),signal() 来休眠 / 唤醒线程。Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
(4)LockSupport
       LockSupport 提供 “创建锁” 和“其他同步类的基本线程阻塞原语”。
  LockSupport 的功能和 “Thread 中的 Thread.suspend()和 Thread.resume()有点类似”,LockSupport 中的 park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。但是 park()和 unpark()不会遇到 “Thread.suspend 和 Thread.resume 所可能引发的死锁” 问题。
(5)CountDownLatch
 CountDownLatch为常用类,它是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
(6)ReentrantLock
Reentrant:可重入
 ReentrantLock 是独占锁。所谓独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。ReentrantLock 锁包括 “公平的 ReentrantLock” 和 “非公平的 ReentrantLock”。”公平的 ReentrantLock” 是指 “不同线程获取锁的机制是公平的”,而 “非公平的 ReentrantLock” 则是指 “不同线程获取锁的机制是非公平的”,ReentrantLock 是 “可重入的锁”。
参考链接
本片文章,主要整理自互联网,便于自己复习知识所用,以下为参考链接!
【1】Java并发编程实战-----“J.U.C”:锁,lock
【2】JUC包中的锁
【4】JUC锁框架综述
JUC同步锁(五)的更多相关文章
- 001-多线程-锁-架构【同步锁、JUC锁】
		一.概述 Java中的锁,可以分为"同步锁"和"JUC包中的锁". 1.1.同步锁 即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁 ... 
- 第十五章、Python多线程同步锁,死锁和递归锁
		目录 第十五章.Python多线程同步锁,死锁和递归锁 1. 引子: 2.同步锁 3.死锁 引子: 4.递归锁RLock 原理: 不多说,放代码 总结: 5. 大总结 第十五章.Python多线程同步 ... 
- JUC——线程同步锁(Condition精准控制)
		在进行锁处理的时候还有一个接口:Condition,这个接口可以由用户来自己进行锁的对象创建. Condition的作用是对锁进行更精确的控制. Condition的await()方法相当于Objec ... 
- 线程同步 synchronized 同步代码块 同步方法 同步锁
		一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ... 
- Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures
		参考博客: https://www.cnblogs.com/xiao987334176/p/9046028.html 线程简述 什么是线程?线程是cpu调度的最小单位进程是资源分配的最小单位 进程和线 ... 
- python 守护进程、同步锁、信号量、事件、进程通信Queue
		一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ... 
- python 全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)
		昨日内容回顾 线程什么是线程?线程是cpu调度的最小单位进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的 一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的在当 ... 
- python事物管理及同步锁
		我们经常会遇到这样子的问题,我给朋友赚钱100,分为两步: 1)我的账户-100 2)朋友账户 +100 看似需求很简单,但是如果在上面的步骤1)结束后,系统崩溃了怎么办? 数据库中有事物管理,也就是 ... 
- Python并发编程-进程 线程 同步锁 线程死锁和递归锁
		进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ... 
随机推荐
- DataX
			#!/bin/bash[ ! -d /opop ] && mkdir /opopcd /opopwget http://192.168.1.129/package/DataX/{jdk ... 
- Luogu P3703 [SDOI2017]树点涂色
			比较有趣的综合树上问题,刷LCT题单时做的但是发现后面LCT只是起了辅助作用233 首先我们分析每一个操作,\(1\)的定义就让我们联想到了access,我们回忆一下LCT的性质: LCT中每一个sp ... 
- ASP.NET Core 发布之后通过命令控制监听地址和环境变量
			添加Command支持 新建一个ASP.NET Core 项目,打开Program.cs 添加下面的代码: public class Program { public static void Main ... 
- Java多线程核心技术(五)单例模式与多线程
			本文只需要考虑一件事:如何使单例模式遇到多线程是安全的.正确的 1.立即加载 / "饿汉模式" 什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接 ... 
- Netty入门(二)之PC聊天室
			参看Netty入门(一):Netty入门(一)之webSocket聊天室 Netty4.X下载地址:http://netty.io/downloads.html 一:服务端 1.SimpleChatS ... 
- ML.NET 示例:聚类之客户细分
			写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ... 
- H5 14-后代选择器和子元素选择器
			14-后代选择器和子元素选择器 <!DOCTYPE html> <html lang="en"> <head> <meta charset ... 
- 最短路问题 Floyd+Dijkstra+SPFA
			参考博客:https://blog.csdn.net/qq_35644234/article/details/60875818 题目来源:http://acm.hdu.edu.cn/showprobl ... 
- Podfile文件用法详解
			https://www.jianshu.com/p/b8b889610b7e 2018.01.09 15:51* 字数 2343 阅读 6263评论 3喜欢 34 前言 iOS开发会经常用到cocoa ... 
- echarts使用笔记二:柱子堆叠
			1.多个柱子堆叠效果,多用于各部分占比 app.title = '坐标轴刻度与标签对齐'; option = { title : { //标题 x : 'center', y : 5, text : ... 
