并发编程<br>
原子性:多个操作要么全部成功,要么全部失败
可见性:一个线程对数据的修改,其他线程可以立马看到
有序性:一个线程内部的所有操作的执行顺序,和代码顺序一致<br>
线程的生命周期
new初始状态<br>当线程被创建,还没有调用start方法时,处于此状态
ready就绪状态-runnable中的ready状态<br> 就绪状态是线程所有资源都得到之后,等待CPU时间片<br>
running运行状态-runnable中的running状态<br> 就绪状态的线程得到cpu时间片后的执行状态
blocked阻塞状态<br>线程因为某种原因放弃CPU时间片,进入阻塞状态<br>
等待阻塞:<br>当某个对象调用wait方法时,作用在这个对象上的当前线程都会被阻塞,并且释放锁<br>只有当这个对象调用notify唤醒这个线程时,这个线程才会进入锁池种抢占锁<br>
同步阻塞:线程在运行的过程中,锁被其他线程抢占,则会放弃CPU时间片,进入锁池中<br>
其他阻塞:例如线程调用sleep、yield方法,会放弃CPU时间片,但不会放弃锁<br> IO阻塞是也会释放CPU时间片,同时释放锁
waiting等待状态的线程,必须等到被唤醒之后才能获取时间片,如果一致不被唤醒,会无限期等待
time_waiting超时等待,处于这个状态的线程,如果长时间没有被唤醒,会自动唤醒<br>
terminated终止状态,当线程的run方法执行结束或者main函数执行结束,线程也就终止<br>
关键字<br>
synchronized
修饰类,静态方法是类锁
修饰成员方法、非静态代码块时,是对象锁
Lock与synchronized的区别
synchronized是Java关键字,修饰方法、类、代码块<br>synchronized生成的锁自动释放,线程得不到锁会一直等待、是可重入、不可中断、非公平锁<br>
Lock是一个接口,需要程序员手动释放锁,线程得不到锁不会一直等待,可重入,可中断,可公平也可不公平<br>
volatile
修饰变量
指令重排的概念<br>
指令重排是值编译器编译优化时,对不存在数据依赖的指令进行重新排序<br>
保证可见性:当线程对volatile修饰的对象进行写操作时,JMM会强行将线程栈中的数据刷新到主内存中<br>
保证有序性:volatile修饰的变量不能够进行指令重排
锁
对象锁:一个对象一把锁
类锁:所有对象一把锁
CAS:比较替换
内存地址值、旧的预期值、要修改的值
线程1要对一个变量进行一个读写操作,首先从内存中读出值,假设是A,然后线程1进行了一系列的操作之后得到了结果B,想要将B写到变量中,但是呢由于线程1在执行操作的过程时间太长,变量的值已经被线程2修改成了C,此时线程1看到变量的值不是A,也就不能将B写进变量中