线程三大特性
原子性:保证线程之间互不影响,每个线程独一无二,保证线程安全问题。
可见性:多个线程之间数据改变后其他线程对其可见。
有序性:控制线程执行顺序,保证有序性,例如:join wait notify(线程之间通信)
JAVA 内存模型:
jmm内存模型决定了多线程并发时全局变量的可见性。
jmm中有一个主内存用于存放所有线程的全局变量,每个线程有一个私有内存,用于存放本线程的私有变量( 注:Java内存模型jmm属于多线程可见性,Java内存结构属于jvm虚拟机)
原理:
有全局变量a = 0,并发时每个线程都会将主内存中的数据备份到自己的私有内存中,若多个线程同时将a+1,则多个线程之间对a的操作是不可见的,就会产生并发问题。
同理在没有发生并发时,第一个线程将a+1,jvm会将更改后的数据刷新到主内存中,这个期间若没有其他线程对a进行写操作,也就不会存在安全问题。
多线程间的同步:
线程问题产生原因:当多个线程对同一个全局变量进行写操作时则会发生安全问题。
synchronized:
释放时机:代码执行完毕或者程序抛出异常都会进行锁的释放。
弊端:同步时会降低效率,阻塞,抢锁。
添加位置:
同步块:synchronized(多个线程的同一对象。任何类型/静态全局变量/this锁){
可能存在线程安全问题的代码
}
同步函数:
非静态同步函数:使用this锁
public synchronized void getValue(){方法体}
静态同步函数:使用当前类的.class文件作为锁
public static synchronized void getValue(){}
ThreadLoca: {ThreadLoca: LocaTest l1 = new LocaTest(number3);}
为每一个线程提供一个全局变量:将一个全局变量添加到ThreadLoca后,在各个线程对其进行修改以后则不会刷新到共享内存中,其内部村行有一个map集合,提供有get(),set()方法,是将当前线程作为key,值作为value,所以也就间接的实现全局变量私有。
Volatile:可以保证全局变量的可见性,但是不能保证其原子性
当某个线程将自己备份的全局变量改变以后,该关键字会强制将改后数据刷新到主内存中。
一般来说当一个线程将全局变量改变后会立即将新数据刷新到主内存中,但是并发时还是会存在时间差,而Volatile就是强制解决这个时间差的。
不能保证线程安全:简单来讲volatile有4个步骤,在执行发送内存屏障这个步骤之前的几步若其他线程将数据进行了更改则会产生线程安全问题。
之上是对线程的一些基本知识总结,下一篇为大家介绍线程安全集合以及线程池的使用原理。