1、线程的五种状态
1)、新建
当new创建一个线程,例如new thread(r),线程还没开始运行,处于新建状态; 2)、就绪 新建的新线程并不会自动运行,要执行需要调用start()方法创建线程运行的系统资源,返回后,此时线程就处于就绪状态; 但是处于就绪状态的线程也并不是就能立即执行run()方法。因为线程必须同其他线程竞争CPU时间,获得CPU时间才能运行线程;(线程数>CPU数)3)、运行
当线程获得CPU时间,进入运行状态,执行run()方法; 4)、阻塞 线程运行过程中,可能由于很多原因进入阻塞状态: 1)、线程通过调用sleep方法进入睡眠状态; 2)、线程试图获得一个锁,但是该锁被其他线程持有; 3)、线程在等待某个处罚条件;(例如定时启动线程) 所谓阻塞就是正在运行的线程没有结束,暂时让出CPU,其他处于就绪的线程就获得CPU时 间,进入运行状态。 5)、死亡 两个原因导致线程死亡: 1)、run()方法正常退出而自然死亡; 2)、一个未捕获的异常终止了run方法而使线程猝死; 用isAlive返回true,则线程可运行或被阻塞。返回false,则线程死亡或者new状态且不是可运行的。2、volitile的理解
当两个线程共享一个数据时,则会有一个共享内存,每个线程又会有一个工作内存。这样的目的是让线程在运行时候从工作内存中拿取数据,加快运行速度,类似一个高速的本地缓存。但是会发生一个问题,就是线程1对共享内存的数据做了改变,线程2还是从工作内存拿数据,导致数据出错。(这个是并发读写常见的出错)。
所以此时就需要volatile,给变量加上valatile字段,就可以解决这个问题。
原理:在加了volatile修饰变量后,如果线程1修改了变量的值,就会在修改工作内存数据后,强制将该数据刷新到共享内存中。如果此时线程2有这个变量的副本,就会强制让线程2的变成缓存失效,不让线程2再次读取和使用。 线程2再次请求数据时,就会去共享内存拿,并且缓存到工作内存中。只是有个缺点,volatile是不能保证原子性的(涉及到复杂的指令重排、内存屏障等概念)。
参考:石杉的架构笔记等公众号。