什么是线程安全
当多个线程同时共享同一个*全局变量或静态变量*,做**写**操作时,可能法神数据冲突的问题(读取数据是不会有线程安全问题的)
线程安全的解决办法
使用多线程之间同步(Synchronized)或锁(lock)
Synchronized用法
- 同步代码块
synchronized(同一个数据){
可能会发生线程冲突问题
}
- 同步函数
在方法上使用synchronized修饰
多线程三大特性
- 原子性
一个操作或多个操作要么全部都执行,要被都不执行 - 可见性
当多个线程访问同一个变量时,一个线程修改了这个变量值,其他线程可以马上知道(和java内存模型相关) - 有序性
程序执行的顺序按照代码的先后顺序执行
java内存模型
JMM决定一个线程对共享变量写入时,能对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
Volatile关键字
volatile作用时变量在多个线程之间可见(但不能保证线程的原子性)
volatile与synchronized区别
仅靠volatile不能保证线程的安全性。(原子性)
- ①volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法
- ②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问
volatile修饰的变量不会阻塞。
synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。
线程安全性
线程安全性包括两个方面,①可见性。②原子性。
从上面自增的例子中可以看出:仅仅使用volatile并不能保证线程安全性。而synchronized则可实现线程的安全性。