1、当多个线程同时共享同一全局变量或静态变量,做写操作时,可能会发生数据冲突问题,也就是线程安全问题。
2、线程安全解决办法之Java内置的锁(synchronized)
2.1、同步代码块
public class Thread01 implements Runnable {
private int trainCount = 100;
public void run() {
while (trainCount > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
sale();
}
}
private void sale() {
synchronized (this) {
if (trainCount > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (100 - trainCount + 1) + "张票!");
trainCount--;
}
}
}
public static void main(String[] args) {
Thread01 t = new Thread01();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
}
}
2.2、同步方法
public class Thread02 implements Runnable {
private int trainCount = 100;
public void run() {
while (trainCount > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
sale();
}
}
private synchronized void sale() {
if (trainCount > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (100 - trainCount + 1) + "张票!");
trainCount--;
}
}
public static void main(String[] args) {
Thread01 t = new Thread01();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
}
}
3、线程安全解决办法之ThreadLocal
public class Res {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 0;
}
};
public Integer getNum(){
int count = threadLocal.get() + 1;
threadLocal.set(count);
return count;
}
}
public class Thread03 extends Thread {
private Res res;
public Thread03(Res res){
this.res = res;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "---" + "i---" + i + "--num:" + res.getNum());
}
}
public static void main(String[] args) {
Res res = new Res();
Thread03 t1 = new Thread03(res);
Thread03 t2 = new Thread03(res);
Thread03 t3 = new Thread03(res);
t1.start();
t2.start();
t3.start();
}
}
4、多线程的三大特性:原子性、可见性、有序性
5、内存模型
总结:什么是Java内存模型:java内存模型简称jmm,定义了一个线程对另一个线程可见。共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。
6、volatile
6.1、用volatile修饰的变量,可保证修改后立即刷新到主内存中,其他线程需要读取时会直接读取主内存中的变量。
6.2、用volatile修饰变量可防止重排序。