线程高级部分
- 线程不安全
- 原子性
- 可见性
- 有序性(指令重排)
线程不安全
多线程下并发同时对共享数据进行读写,会造成数据混乱=线程不安全
当多线程下并发访问临界资源时,如果破坏其原子性、可见性、有序性,可能会造成数据不一致。
原子性
原子性操作指相应的操作是 单一不可分割的操作。
可见性
指当多个线程访问同一个资源时,一个线程修改了资源,其他线程能够立即看到修改的值
- 比如下面的代码就违反了可见性
public class ThreadPool {static boolean alwasy=true;public static void main(String[] args) throws ExecutionException, InterruptedException {new Thread(()->{while (alwasy){}}).start();Thread.sleep(2000);alwasy=false;}
}
原因:两个线程共享主内存变量,复制了两份副本,我们改变的只是主线程的变量 另外一个线程的没有改过来。主内存改了后并不会同步到主内存中。
- 解决方法:使用synchronized ,synchronized 在解锁之前会将变量同步到主内存中
public class ThreadPool {static Boolean alwasy=true;public static void main(String[] args) throws ExecutionException, InterruptedException {new Thread(()->{while (alwasy){synchronized (alwasy){}}}).start();Thread.sleep(2000);alwasy=false;}
}
对一个变量解锁之前,必须先把此变量同步回主内存中,这样解锁后,线程就可以访问被修改后的值
所以synchronized 锁住的对象,其值具有可见性
- 非常重要
使用 System.out.println();也可以的,因为System.out.println();里面也实现了synchronized 锁
synchronized的锁,任意一个被锁住的对象,只要锁释放了,就会把工作内存中变量同步到主内存
public class ThreadPool {static Boolean alwasy=true;public static void main(String[] args) throws ExecutionException, InterruptedException {new Thread(()->{while (alwasy){//这个也可以System.out.println();}}).start();Thread.sleep(2000);alwasy=false;}
}