线程安全问题:内存可见性
public class ThreadSafe {
//此时线程2将f改成true,但线程1看不到;会一直循环在while (!f)里
static boolean f=false;
public static void main(String[] args) {
Thread thread1=new Thread(()->{
System.out.println("启动");
while (!f){
}
System.out.println("结束");
});
thread1.start();
Thread thread2=new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f=true;
});
thread2.start();
}
}
解决上面的线程安全问题:
1.利用 Volatile:保证内存可见性,但不保证原子性
public class Volatile {
//此时线程2将f改成true,线程1可看到;不会一直循环在while (!f)里,会输出“结束”
volatile static boolean f=false;
public static void main(String[] args) {
Thread thread1=new Thread(()->{
System.out.println("启动");
while (!f){
}
System.out.println("结束");
});
thread1.start();
Thread thread2=new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f=true;
});
thread2.start();
}
}
2.利用 Synchronized:保证内存可见性、
还可保证原子性https://blog.youkuaiyun.com/xhhhx_/article/details/124127014
public class Synchronized {
static boolean f=false;
public static void main(String[] args) {
Object object=new Object();
//当线程2将f改成true,线程1可看到
Thread thread1=new Thread(()->{
System.out.println("启动");
while (true){
//在线程2没修改f之前,线程1会重复进行加锁、放锁操作;每次加锁利用synchronized,都会从主内存拷贝变量f的最新副本到工作的内存,
synchronized (object) {
if(f){
System.out.println("结束");
break; //跳出while循环
}
}
//释放了锁,还在while循环里
}
});
thread1.start();
Thread thread2=new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f=true;
});
thread2.start();
}
}