目录

  • 一、JVM内存区域
  • 二、JVM内存模型(Java Memory Model,简称JMM)
  • 三、各个线程运行期间必须遵守的规定
  • 四、wait与notify
  • 五、tryLock
    • 1、代码实例
    • 2、lock()和tryLock()有何不同?
  • 六、AQS源码分析
    • 1、state
    • 2、访问state的方法
    • 3、加锁方式
    • 4、独占方式的加锁与解锁
    • 5、共享方式的加锁与解锁
    • 6、CountDownLatch
    • Java高并发编程实战系列文章
    • 哪吒精品系列文章

一、JVM内存区域

JVM在运行时,会将其管理的内存区域划分为方法区、堆、虚拟机栈、本地方法栈和程序计数器5个区域;

  • 方法区和堆是所有下城共享的区域;
  • 虚拟机栈、本地方法栈、程序计数器是各个线程私有的;

二、JVM内存模型(Java Memory Model,简称JMM)

JMM用于定义程序汇总变量的访问规则,即在JVM中如何将变量存储到内存,以及如何从内存中获取变量(此处变量指所有线程共享的变量)。

与JVM内存区域不同,JMM是从另一个角度对内存进行划分,分为主内存和工作内存。

JMM规定所有的变量都存储在主内存中,每个线程还拥有自己独立的工作内存。主内存中的变量会通过复制的方式留给线程的工作内存一个副本,供各个线程独立使用。 线程对变量的所有读写操作都是在工作内存中进行的,工作内存中的副本变量会通过JMM与主内存中的原变量保持同步。

三、各个线程运行期间必须遵守的规定

  1. 只能方案文自己工作内存中的变量;
  2. 无法直接访问其他线程工作内存中的变量;
  3. 可以通过主内粗间接访问其他线程工作内存中的变量;

四、wait与notify

多个线程在争夺同一个资源时,为了让这些线程协同工作、提高CPU利用率,可以让线程之间进行沟通,具体可以通过wait()和notify()实现。

  1. wait():使当前线程处于等待状态,即阻塞,直到其它线程调用此对象的notify()方法;
  2. notify():唤醒在此对象监视器上等待的单个线程,如果有多个线程同时在监视器上等待,则随机唤醒一个;
  3. notifyAll():唤醒在此对象监视器上等待的所有线程;

使用时需要注意几点:

  1. 三个方法都是Object()类中定义的native方法,而不是thread类提供的,这是因为Java提供的类是对象级的,而不是线程级的;
  2. 这三个方法都必须在synchronized修饰的方法或代码块中使用,否则会抛出异常;
  3. 使用wait()时,为了避免并发带来的问题,通常建议将wait()方法写在循环的内部。

五、tryLock

tryLock的意思是,当一个线程尝试加锁失败后,会再次请求,持续一段时间,如果一直失败则放弃加锁。

1、代码实例

package com.guor.demo.thread;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TryLockTest extends Thread{Lock lock = new ReentrantLock();@Overridepublic void run() {// 获取线程名称String threadName = Thread.currentThread().getName();boolean isLocked = false;try {// 在2秒内尝试加锁isLocked = lock.tryLock(2, TimeUnit.SECONDS);// 加锁成功if(isLocked){Thread.sleep(1000);System.out.println(threadName+"加锁成功");}else {System.out.println(threadName+"加锁失败");}} catch (InterruptedException e) {System.out.println(threadName+"tryLock 异常:"+e);}finally {if(isLocked){lock.unlock();System.out.println(threadName+"解锁");}}}public static void main(String[] args) {TryLockTest thread1 = new TryLockTest();TryLockTest thread2 = new TryLockTest();thread1.setName("线程1");thread2.setName("线程2");thread1.start();thread2.start();}
}

2、lock()和tryLock()有何不同?

  • lock():尝试获取锁,如果锁被占用则等待;
  • tryLock():尝试获取锁,如果锁被占用则返回false,则不再等待,如果锁未被占用,则立刻获取锁,并返回true;
  • tryLock(long time, TimeUnit unit):在tryLock()的基础上,如果锁被占用,则会在一段时间内不断地尝试获取锁,直至成功获取锁;
  • lockInterruptibly():一个线程加锁之后,其它线程因为无法获取锁而导致的等待状态可以被中断;

六、AQS源码分析

1、state

在AQS中维护着一个表示共享资源加锁情况的变量 volatile int state,以及一个FIFO的线程阻塞队列(称为CLH队列)。当多个线程并发访问共享资源时,如果共享资源已经被某个线程加了锁,那么其它线程在访问此共享资源时就会加入CLH队列。


state表示共享资源被线程加锁的次数。

当state的值为1时,就表示共享资源被某个线程加了一次锁;
当state的值为0时,表示共享资源没有被加锁,随时可以访问;

2、访问state的方法

  1. int getState(),获取state值;
  2. void setState(int newState),设置state值;
  3. compareAndSetState(int expect,int update),使用哪个CAS算法,设置state值;

3、加锁方式

  1. Exclusive:独占方式,同一时间内只能有一个线程访问资源,如ReentrantLock采用的是独占方式;
  2. Share:共享方式,同一时间内允许多个线程并发访问资源,如CountDownLatch采用的就是共享方式;

4、独占方式的加锁与解锁

  1. boolean tryAcquire(int arg):尝试获取资源,如果成功,就给该资源加arg个锁,并独占该资源;
  2. boolean tryRelease(int arg):尝试释放资源,如果成功,就释放该资源的arg个锁;
  3. boolean isHeldExclusively():判断当前线程,是否正在独占共享资源;

例如ReentrantLock的state初始值为0,当某个线程调用lock()方法时,lock()就会在底层触发tryAcquire(1),把该资源的state修改为1,表示该资源加了一把锁,之后就可以独占使用该资源,之后再调用lock()就会失败并进入阻塞状态(因为ReentrantLock是独占方式,同一时间只能被一个线程加锁),只有在该线程调用哪个unlock()的时候,会在底层触发tryRelease(1)将state的值变为0,也就是释放锁。

5、共享方式的加锁与解锁

(1)int tryAcquireShared(int arg)

  1. 尝试给太资源加arg个共享锁,并访问该资源;
  2. 返回负数:加锁失败,当前线程进入CLH等待;
  3. 返回0:当前线程加锁成功,但后续其它线程无法再加共享锁;
  4. 返回整数:当前线程加锁成功,并且后续线程也可以再加共享锁;

(2)tryReleaseShared(int arg)

尝试释放该资源的arg个锁。

6、CountDownLatch

CountDownLatch的构造方法CountDownLatch(int count)可以将state的初始值设置为count,并交给count个线程去并发执行,于此同时,主线程进入阻塞状态。当每个子线程执行完毕后,都会调用一次countDown(),countDown()会在底层调用tryReleaseShared(1),即把state减1。

因此,当所有子线程全部执行完毕后,state的值就会变为0,此时唤醒主线程,从而实现了闭锁功能

Java高并发编程实战系列文章

Java高并发编程实战1,那些年学过的锁

Java高并发编程实战2,原子性、可见性、有序性,傻傻分不清

Java高并发编程实战3,Java内存模型与Java对象结构

Java高并发编程实战4,synchronized与Lock底层原理

Java高并发编程实战5,异步注解@Async自定义线程池

哪吒精品系列文章

Java学习路线总结,搬砖工逆袭Java架构师

10万字208道Java经典面试题总结(附答案)

SQL性能优化的21个小技巧

Java基础教程系列

Spring Boot 进阶实战

Java高并发编程实战6,通过AQS源码分析lock()锁机制相关推荐

  1. 高并发编程-Thread#interrupt用法及源码分析

    文章目录 官网 方法&源码 void interrupt() ` boolean isInterrupted()` vs `static boolean interrupted()` 方法&a ...

  2. 【Java并发编程】16、ReentrantReadWriteLock源码分析

    一.前言 在分析了锁框架的其他类之后,下面进入锁框架中最后一个类ReentrantReadWriteLock的分析,它表示可重入读写锁,ReentrantReadWriteLock中包含了两种锁,读锁 ...

  3. Java并发编程(十六):CyclicBarrier源码分析

    前言   CyclicBarrier可以建立一个屏障,这个屏障可以阻塞一个线程直到指定的所有线程都达到屏障.就像团队聚餐,等所有人都到齐了再一起动筷子.根据Cyclic就可以发现CyclicBarri ...

  4. c++ 线程池_JAVA并发编程:线程池ThreadPoolExecutor源码分析

    前面的文章已经详细分析了线程池的工作原理及其基本应用,接下来本文将从底层源码分析一下线程池的执行过程.在看源码的时候,首先带着以下两个问题去仔细阅读.一是线程池如何保证核心线程数不会被销毁,空闲线程数 ...

  5. Java并发编程笔记之Semaphore信号量源码分析

    JUC 中 Semaphore 的使用与原理分析,Semaphore 也是 Java 中的一个同步器,与 CountDownLatch 和 CycleBarrier 不同在于它内部的计数器是递增的,那 ...

  6. java并发编程基础-ReentrantLock及LinkedBlockingQueue源码分析

    ReentrantLock是一个较为常用的锁对象.在上次分析的uil开源项目中也多次被用到,下面谈谈其概念和基本使用. 概念 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 相 ...

  7. Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...

    JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...

  8. 29W 字总结阿里 Java 高并发编程:案例 + 源码 + 面试 + 系统架构设计

    下半年的跳槽季已经开始,好多同学已经拿到了不错的 Offer,同时还有一些同学对于 Java 高并发编程还缺少一些深入的理解,不过不用慌,今天老师分享的这份 27W 字的阿里巴巴 Java 高并发编程 ...

  9. Java 7并发编程实战手册

    2019独角兽企业重金招聘Python工程师标准>>> Java 7并发编程实战手册 本书是 Java 7 并发编程的实战指南,介绍了Java 7 并发API 中大部分重要而有用的机 ...

  10. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

最新文章

  1. 全国计算机二级计基础题第十五套,计算机等级考试:二级VFP机试第15套
  2. unity, 由5.2.1f1升级到5.3.5f1,2d物理不正常解法
  3. jquery实现动态五角星评分
  4. 最新最全的视觉Transformer教程!论文分析 + 逐行Coding,带你轻松玩转ViT
  5. [react] 在React中声明组件时组件名的第一个字母必须是大写吗?为什么?
  6. 人工智能领域中声源定位的研究与发展------第一章 绪论
  7. 【Flink】Flink实验特性--reinterpretAsKeyedStream 将DataStream重新解释为KeyedStream
  8. 涉及到整型参数时,没有初始化时,Debug下可以运行,但是Release下不行
  9. java导入excel数据到mysql_java的poi技术读取Excel数据到MySQL
  10. 如果你手头有20万,你是拿去买房还是拿去投资?
  11. CentOS_Oracle Enterprise Manager 11g 页面中文无法显示
  12. linux shell 十进制转十六进制_问1得10:shell十进制转换到任意进制,多大事儿,一行搞定!
  13. Linux Linux函数 Linux聊天程序 基于socket的TCP(有连接的)聊天程序
  14. 安装程序未能打开日志文件_安装和启动日志错误 | Adobe Creative Suite 6、Adobe Creative Suite 5.5、Adobe Creative Suite 5...
  15. Redis更新数据的时候如何不重置过期时间
  16. python一般用什么平台好_python哪几个平台好用
  17. 机器学习原理与实践(开源图书)-总目录
  18. 英语形容词的排列顺序
  19. nginx PHP499错误,Nginx日志错误码499的问题解决方法
  20. 境外诈骗,最新来自senegal的邮件诈骗

热门文章

  1. 2020.10.12--PS--制作图章、抽出滤镜、消失点
  2. c语言选择结构训练试题,C语言临考练习试题
  3. C#控制Bartender自动列印的2种方法(附源码)
  4. Java 替换word文档文字
  5. 凤凰项目-----读书笔记
  6. python做bi系统_如何用开源bi,打造自己的轻量级bi系统
  7. linux终端哪个好看,关于linux:Linux-终端最全推荐建议收藏
  8. 北理工嵩天Python语言程序设计笔记
  9. 解决IDEA中leetcode插件出现中文乱码问题
  10. 时间序列分类实践介绍(使用Python代码)