多线程基础
一、并发与并行的区别:
**并发:**多线程操作同一个资源。
- CPU 只有一核,模拟出来多条线程,天下武功,唯快不破。那么我们就可以使用CPU快速交替,来模拟多线程。
- 并发编程的本质:充分利用CPU的资源!
并行: 多个人一起行走
- CPU多核,多个线程可以同时执行。 我们可以使用线程池!
多线程的内存图:
二、线程的状态:
1)new新建状态
2)block阻塞
3)runnable运行
4)terminated死亡
5)sleep休眠
6)waiting无线等待
wait/sleep的区别:
1、来自不同的类
wait => Object
sleep => Thread
一般情况企业中使用休眠是:
TimeUnit.DAYS.sleep(1); //休眠1天
TimeUnit.SECONDS.sleep(1); //休眠1s
2、关于锁的释放
wait 会释放锁;
sleep睡觉了,不会释放锁;
3、使用的范围是不同的
wait 必须在同步代码块中;
sleep 可以在任何地方睡;
4、是否需要捕获异常??好像有问题
wait是不需要捕获异常;
sleep必须要捕获异常;
三、synchronize锁
公平锁: 十分公平,必须先来后到~;
非公平锁: 十分不公平,可以插队;(默认为非公平锁)
synchronized锁的是多线程竞争的资源(需要增删改的对象)
synchronize作为多线程关键字,是一种同步锁,它可以修饰以下几种对象:
-
代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号{ }里的代码,作用的对象是调用这个代码块的对象;
synchronized(锁对象){//锁对象:可以是任意对象,但必须保证多个线程使用的锁对象是同一个 可能出现安全问题的代码块 }
-
方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象
-
静态方法:不是this,this是创建对象后产生的,静态方法优先于对象,锁作用的范围是整个静态方法,作用的对象是本类的的class类,class文件文件对象(反射)。
-
类:作用的范围是synchronize后面括号里的部分,作用的对象是这个类的所有对象
四、Lock锁
java.util.concurrent.locks.ReentrantLock implements Lock 接口
1)Synchronized 与Lock 的区别
- 存在层面:Syncronized 是Java 中的一个关键字,存在于 JVM 层面,Lock 是 Java 中的一个接口
- 锁的释放条件:1. 获取锁的线程执行完同步代码后,自动释放;2. 线程发生异常时,JVM会让线程释放锁;Lock 必须在 finally 关键字中释放锁,不然容易造成线程死锁
- 锁的获取: 在 Syncronized 中,假设线程 A 获得锁,B 线程等待。如果 A 发生阻塞,那么 B 会一直等待。在 Lock 中,会分情况而定,Lock 中有尝试获取锁的方法,如果尝试获取到锁,则不用一直等待
- 锁的状态:Synchronized 无法判断锁的状态,Lock 则可以判断
- 锁的类型:Synchronized 是可重入,不可中断,非公平锁;Lock 锁则是 可重入,可判断,可公平锁可以自己设置公平锁和非公平锁;
- **锁的性能:**Synchronized 适用于少量同步的情况下,性能开销比较大。Lock 锁适用于大量同步阶段:
- Lock 锁可以提高多个线程进行读的效率(使用 readWriteLock)
- 在竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
- ReetrantLock 提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。