线程的内存
• 可见性:jvm为了加快性能,对于多cpu,会将线程要用到的的对象值从共享内存拷贝一份出来,放在这个线程的缓存里,在每次被线程访问时,都是从自己的缓存中读取该值,如果有修改,则在线程结束时把值写回共享内存。这就意味着,如果两个线程看似操作同一个变量,但是另一个线程改变了这个变量,不会立刻刷新共享内存,同样,一个线程一旦获取到这个变量,后续也很可能不再从共享内存中读取新值,而是从缓存中拿旧的值。volatile保证了一个变量的修改立刻对所有线程可见,就叫做可见性。
• 原子性:原子性是针对一条Cpu指令而言,而不是针对一条语句;因为一条语句比如调用一个方法,背后也可能是多条语句或者指令执行完成(比如inta++,其实是先获取inta的值,然后+1,然后写回ibta三步)。如果我们能保证某一组语句要么全部被执行完成,要么全部不被执行,那么这组语句就具备原子性。比如加了synchronized的方法,我们就可以认为其具备原子性。

线程创建Thread:支持两种方式创建线程,但其实都是基于Thread类,它提供了两种构造函数,一种是不传参,一种是传入Runnable接口对象。
• extends Thead类,这种方式下,新建的类本身就是一个Thread子类(通过 new ThreadClass()来创建一个线程,如果想要启动多个线程,就需要new 多个对象实例);线程间的数据共享,通过线程类中的static成员,或者访问线程外的其它某一个独立的实例完成。
• implements Runnable接口(需要实现接口Runnable中的run方法,Thread类本身也是实现的该接口),然后ainstance=new RunnableClass(),再把对象实例作为一个参数传递给Thread构造函数,如new Thread(ainstance)(如果想要启动多个线程,new多个Thread即可,new的时候可以传入同一个ainstance);线程间的数据共享,可以通过访问和操作ainstance实现。

线程状态Enum Thread.State
• 基于Object针对对象monitor锁的控制:多线程中如果不涉及资源同步也就是需要锁的竞争,就不需要控制锁。synchronized(控制锁的自动获取和自动释放),wait(控制线程的挂起,记住挂起的位置,并自动释放锁),notify(唤醒任一/所有notifyAll已经获取到该对象锁并且被挂起了的线程,线程需要重新获取锁,然后从挂起的位置开始执行)。wait和notify只能在synchronized定义的方法里才能使用,但是它们是基于Object对象实例的方法,所以当对个线程操作一个实例时,可以用于线程间的通信。
• 基于Thread针对线程自身的控制:多线程总会涉及到CPU的竞争,即一个CPU同一时间只能运行一个线程(多个CPU可以运行多个)。sleep(暂停运行,让出一定时间的cpu,然后继续运行),yield(暂停运行,重新和其它线程一起竞争CPU)。这两个是基于Thread的静态方法,所以在任何地方都可以使用,但是只能作用于自己所在的线程。
• 基于Thread针对线程实例的控制:start(启动线程,即把线程提交给虚拟机调度,虚拟机会调用run方法),join(等待这个线程实例执行完成,再往下走),interrupt(如果线程是中断状态则让线程跳出中断继续进入执行态,也正因此wait/sleep/join调用时,需要trycatch InterruptedException,来处理被中断时要做的事情。如果线程正在执行,则将线程的Isinterrupted标志位置为true,线程内部可以通过读取这个标志位来决定做什么事比如退出)。基于实例的控制,使得在线程外部,只要拿到这个线程的实例,也可以操控这个线程。

lock atomic
JAVA笔记五:多线程

相关文章: