java内存模型中的volatile关键字保证:
- 保证多线程共享变量的可见性,但是不能保证原子性
- synchronized 关键字保证了操作的原子性,可见性,但是不能保证指令重拍
- volatile关键字保证了指令的重排序,java内存模型要求对volatile变量的写操作先与volatile变量的读操作
看代码
package com.bootdo.testDemo.rpc;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
class MyList{
private volatile List<Integer> list=new ArrayList<>();
public void add(int data){
list.add(data);
}
public int getSize(){
return list.size();
}
}
class ThreadB extends Thread{
private MyList myList;
public ThreadB(MyList myList){
super();
this.myList=myList;
}
@Override
public void run() {
try{
while(true){
if(myList.getSize()==2){
System.out.println("threadB interrupt");
throw new InterruptedException();
}
//System.out.println("threadB size="+myList.getSize());
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class ThreadA extends Thread{
private MyList myList;
public ThreadA(MyList myList){
super();
this.myList=myList;
}
@Override
public void run() {
for(int i=0;i<3;i++){
myList.add(3);
System.out.println("threadA add :size="+myList.getSize());
try {
//注意这里休眠是为了保证让出cpu运行时间,保证线程ThreadB运行,让两个线程交替运行
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo {
static volatile MyList myList=new MyList();
public static void show(){
Thread threada=new ThreadA(myList);
Thread threadb=new ThreadB(myList);
threada.setName("threada");
threadb.setName("threadb");
threada.start();
threadb.start();
}
public static void main(String[] args) {
ThreadDemo2 threadDemo2=new ThreadDemo2();
new Thread(threadDemo2,"threadDemo2").start();
while(true){
System.out.println(" hahaha......"); //1 可以导致线程中断
/**
* public void println(String x) {
* synchronized (this) {
print(x);
newLine();
}
}
*/
synchronized (ThreadDemo.class){} //2 可以导致线程中断
ThreadDemo.test2(); //3可以导致线程中断 synchronized 保持线程的可见性
ThreadDemo.test1(); //4 main 线程陷入死循环
if(threadDemo2.flag){
System.out.println("main thread exit :");
break;
}
}
}
public static void test1(){}
public static synchronized void test2(){}
static class ThreadDemo2 extends Thread{
private boolean flag=false;
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
System.out.println(Thread.currentThread().getName()+" 线程结束:flag="+flag);
}
}
}