Java多线程复习整理(二)
目录
1. 线程的五种状态(操作系统层面)?
2.线程的状态(JAVA层面)?
3.. 线程相关的基本方法?
4. wait()和sleep()的区别?
5.sleep()方法和yield()方法区别?
6.synchronized和Lock(ReentrantLock)有什么区别?
7.同步锁、死锁、乐观锁、悲观锁?
8.synchronized原理进阶(锁膨胀)?
1. 线程的五种状态(操作系统层面)?
这是从操作系统层面来描述的:
- 初始状态:仅是在语言层面创建了线程对象,还未与操作系统的任务调度器组件相关联。
- 就绪状态:指该线程已经被创建,同时已经被操作系统的任务调度器所管理,只需要等待系统分配给该线程CPU的时间片,就可以由CPU调度执行。
- 运行状态:指该线程获取到了CPU的时间片,正在被CPU执行。当CPU的时间片用完,会从运行状态转换至就绪状态,同时会进行线程的上下文切换。
- 阻塞状态:如果调用了阻塞API,如BIO读写文件。这时该线程实际上不会用到CPU,会导致线程的上下文切换,进入阻塞状态。等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至就绪状态。与就绪状态的区别是:对于阻塞状态的线程来说只要它们一直不唤醒,操作系统的任务调度器就一直不会考虑调度它们,给他们分配CPU的时间片。
- 终止状态:表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态。
2.线程的状态(JAVA层面)?
1. New -> 新建状态:创建了线程对象,但是并没有调用该对象的start方法,这时线程处于创建状态。
2. Runnable -> 就绪状态:当调用了线程对象的start方法之后,该线程就进入了就绪状态。但是此时操作系统的任务调度器程序还没有把该线程设置为当前线程,所以该线程此时处于就绪状态。
3. Running -> 运行状态:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run方法当中的代码。
4. 阻塞状态:阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(1) Waiting -> 等待状态:通过调用线程的wait()方法,让线程等待某工作的完成。
(2) Timed_Waiting -> 超时等待状态:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
(3) Blocked -> 同步阻塞状态:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
5. Terminated -> 终止状态:线程执行完了或者因异常退出了run()方法时,该线程就会结束生命周期,进入到终止状态。
3.. 线程相关的基本方法?
线程相关的基本方法有wait(),notify(),notifyAll(),sleep(),join(),yield()等。
1.线程等待(wait())
调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回。需要注意的是调用wait()方法后,会释放对象的锁。因此wait()方法一般需要绑定synchronized同步关键字,一起在同步方法或者同步代码块中使用。
2.线程睡眠(sleep())
sleep()方法会导致当前线程休眠,与wait()方法不同的是,sleep()方法不会释放当前占有的锁。sleep(long)方法会导致线程进入TIMED-WATING状态,而wait()方法会导致当前线程进入WATING状态。
3.线程让步(yield())
yield()方法会使当前线程让出CPU执行的时间片,与其他线程一起重新竞争 CPU的时间片。一般情况下,优先级高的线程有更大的可能性成功竞争得到 CPU 的时间片。但这又不是绝对的,有的操作系统对线程的优先级并不敏感。
4.线程中断(interrupt())
中断一个线程,其本意是给这个线程一个通知信号,会影响这个线程内部的一个中断标识位。但是这个线程本身并不会因此而改变状态(如阻塞,终止等)。
5.等待其他线程终止(join())
join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转为阻塞状态。等到另一个线程结束,当前线程再由阻塞状态变为就绪状态,然后等待操作系统的任务调度器组件给其分配CPU的时间片。
6.线程唤醒(notify()和notifyAll())
Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程,选择是任意的。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争,来获取CPU的时间片。类似的方法还有notifyAll(),唤醒在此监视器上等待的所有线程。
4. wait()和sleep()的区别?
1. 来自不同的类
wait():来自Object类;
sleep():来自Thread类;
2.关于锁的释放:
wait():在等待的过程中会释放锁;
sleep():在等待的过程中不会释放锁
3.使用的范围:
wait():必须在同步代码块中使用;
sleep():可以在任何地方使用;
4.是否需要捕获异常
wait():不需要捕获异常;
sleep():需要捕获异常;
5.sleep()方法和yield()方法区别?
sleep()方法:
1. 调用sleep()方法会让当前线程从Running状态进入Timed_Waiting状态(阻塞)
2. 其它线程可以使用interrupt()方法来打断正在睡眠的线程,这时sleep()方法会抛出InterruptedException异常。
3. 睡眠结束后的线程未必会立刻得到执行。
4. 建议使用TimeUnit类的sleep()方法来代替Thread类的sleep()方法来获得更好的可读性。
yield()方法:
1. 调用yield()方法会让当前线程从Running状态进入到Runnable状态。然后CPU可以调度执行其它线程。
2. yield()方法具体的实现依赖于操作系统的任务调度器组件。
6.synchronized和Lock(ReentrantLock)有什么区别?
- 首先synchronized是Java内置的关键字,是在Jvm的层面。而ReentrantLock是个JDK自带的Java类。
- synchronized无法判断是否获取锁的状态。而ReentrantLock可以判断是否获取到锁。
- synchronized会自动释放锁(a. 线程执行完同步代码块后会释放锁。b. 线程执行过程中发生异常会释放锁)。ReentrantLock需在finally代码块中手动释放锁(unlock()方法释放锁),否则容易造成线程死锁。
- 用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2就会等待。如果线程1阻塞,线程2则会一直等待下去。而ReentrantLock锁就不一定会等待下去,如果获取不到锁,线程可以不用一直等待就结束了。
- Synchronized关键字锁特点:可重入、不可中断、非公平。而ReentrantLock锁特点:可重入、可判断、可以设置为公平锁(两者皆可)。
- ReentrantLock锁适合大量同步的代码的同步问题。而synchronized锁适合代码少量的同步问题。
7.同步锁、死锁、乐观锁、悲观锁?
同步锁:
当多个线程同时访问同一个共享数据时,很容易出现问题。为了避免这种情况出现,我们要保证线程同步互斥,就是指并发执行的多个线程,在同一时间内只允许一个线程访问共享数据,来保证原子性,可见性以及有序性等条件。Java中可以使用synchronized关键字来取得一个对象的同步锁。
死锁:
何为死锁,就是两个或者多个线程同时被阻塞住,它们中的一个线程或者全部线程都在等待某个资源被释放。(比如:t1线程获得到了A对象锁,接下来想获取B对象的锁,t2线程获得到了B对象锁,接下来想获取A对象的锁,它们都持有对方想要的资源,但是又不肯释放自己所占有的资源,所以双方都进入到了阻塞状态。比如著名的哲学家就餐问题)。
乐观锁:
总是假设最好的情况,每次去拿数据的时候都会认为别人不会去修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,就像数据库提供的类似于write_conditio机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS来实现的。
悲观锁:
总是假设最坏的情况,每次去拿数据的时候都会认为别人会修改,所以每次在拿数据的时候都会上锁。这样别人想拿这个数据就会被阻塞住,直到它拿到锁为止(共享资源每次只给一个线程使用,其它的线程会被阻塞住,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized同步锁关键字和ReentrantLock可重入锁等独占锁就是悲观锁思想的实现。
8.synchronized原理进阶(锁膨胀)?
首先:Java HotSpot虚拟机中,每个对象都有对象头(包括class指针和 Mark Word)。Mark Word平时存储这个对象的哈希码、分代年龄。当加锁时,这些信息就根据情况被替换为标记位、线程锁记录指针、重量级锁指针、线程ID等内容。
轻量级锁:轻量级锁的使用场景:如果一个对象(共享变量)虽然有多个线程要访问,但加锁的时间是错开的(也就是说没有竞争),那么可以使用轻量级锁来优化。轻量级锁对使用者是透明的,即语法仍然是synchronized。
重量级锁:如果在尝试加轻量级锁的过程中,CAS操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。
自旋优化:重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这时候持锁线程已经退出了同步块,释放了锁),这时当前线程就可以避免阻塞。
偏向锁:轻量级锁在没有竞争时(就自己这个线程),每次重入时仍然需要执行 CAS操作。Java 6中引入了偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS。以后只要不发生竞争,这个对象就归该线程所有。
锁消除:JVM会进行代码的逃逸分析,例如某个加锁对象是方法内的局部变量,不会被其它线程所访问到。这时候就会被即时编译器(JIT)忽略掉所有同步操作。
Java多线程复习整理(二)相关推荐
- Java多线程闲聊(二):活锁和死锁
Java多线程闲聊(二):活锁和死锁 这两个情况其实都是应该需要避免的情况,为了便于自己的回顾,我还是希望通过尽可能简单的表达来进行简要的归纳. 何谓死锁,就是正正紧紧按照Java的规范进行编程依然会 ...
- Java多线程学习(二)synchronized关键字(1)
转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...
- 【Java进阶营】JAVA多线程基础学习二:synchronized
本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题,没错就是使用synchronized. 一.如何解决线程安全问题? 一般 ...
- Java多线程--设计模式(二、Immutable Object(不可变对象)模式)
一.Immutable Object 模式简介 多线程共享变量的情况下,为了保证数据的一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object 模式使 ...
- Java多线程详解(二)
评论区留下邮箱可获得<Java多线程设计模式详解> 转载请指明来源 1)后台线程 后台线程是为其他线程服务的一种线程,像JVM的垃圾回收线程就是一种后台线程.后台线程总是等到非后台线程死亡 ...
- JSP Java 期末复习整理
Java 期末复习 第一章 1.1.1 JSP 1.1.2 Jsp 优点 1.2.2 B/S技术工作原理 1.2.3 如何访问动态网页 1.2.4 -- Tomcat目录结构 1.2.6 -- Web ...
- NCAE(全国工业和信息化应用人才考试 )-- 服务外包 JAVA 软件开发复习整理(二)
自然排序的一些细节:空格排在字符前.大写字符排在小写字符前 TreeSet集合放入的对象要求是能进行比较排序的: 如下代码,在TreeSet放入的元素有String和Integer两种类型,在编译时不 ...
- java多线程复习与巩固(二)
synchronized关键字详解 synchronized早期是重量级锁,是因为只要使用synchronized关键字都会调用操作系统内核(用户态--> 内核态).1.6版本引入偏向锁和自旋锁 ...
- java多线程总结(二)
线程一般有6个状态: 新建状态:NEW 可运行状态:RUNNABLE 休眠状态:TIMED_WAITING 等待状态:WAITING 阻塞状态:BLOCKED 终止状态"TERMINATED ...
最新文章
- Science:科学家亲眼看到细菌产生耐药性的全过程(视频)
- vue父子组件传值,sync语法糖
- 好久没来了,发个招聘贴
- Bypass WAF Cookbook
- Application Architecture Guide 2.0 (Chapter 7: Quality Attributes) Part 3
- [Android]你不知道的Android进程化(2)--创建进程
- 数字ab写成c语言表达式,《C语言程序设计》复习题(21页)-原创力文档
- 看徐坤的话剧《性情男女》
- linux读写usb host,LINUX下USB1.1设备学习小记(3)_host与device
- 响应式布局 max-device-width 与 max-width 的区别
- VTP实现VLAN同步
- ThingJS平台制作第一人称视角下的巡更效果
- IDEA 创建maven jar、war、 pom项目
- Oracle数据库merge into的使用,存在则更新,不存在则插入
- HALCON 20.11:深度学习笔记(5)---设置超参数
- 最速下滑法c语言程序,最速下降法 C语言.doc
- 学习笔记(3)-重叠社区发现Copra算法
- 生物信息学中用到的计算机知识,生物信息学期末复习知识点总结
- win10无法打开设置,桌面右键显示设置提示ms-settings:display 该文件没有与之关联的程序来执行该操作
- STL 常用容器的底层数据结构实现
热门文章
- wifi有网可以连接,但打不开网页了,找不到 服务器 dns 地址
- fastadmin btn-ajax,FastAdmin 在线命令生成时出错的分析
- html横幅设置,如何控制HTML横幅的宽度和高度?
- 【从零开始学深度学习编译器】十二,MLIR Toy Tutorials学习笔记一
- 打2把王者荣耀的时间,学会JAVA自制验证码图片
- DenseBox Unifying Landmark Localization with End to End Object Detection
- SVN删除tags旧版本失败
- 网络层(ip地址划分以及路由)
- ACdream 之ACfun 题解
- F1 Score详解 查准率较高 召回率较低怎末处理?