"原子操作(atomic operation)是不需要synchronized",这是Java多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切 换到另一个
原子操作
原子操作(atomic operation),是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何的线程切换。如java并发包中的类方法,都是原子操作。
内存可见性
内存可见性(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态后,其他线程能够立即看到发生的状态变化。
由于线程之间的交互都发生在主内存中,但对于变量的修改又发生在自己的工作内存中,经常会造成读写共享变量的错误,我们也叫可见性错误。
可见性错误是指当读操作与写操作在不同的线程中执行时,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。
volatile关键字可以解决内存的可见性问题,用volatile修饰的变量,当其改变时,会实时、强制更新到其他线程的私有内存和主线程中。
指令重排序
在线程内观察时,一切操作都是有序的;在一个线程看另一个线程时,一切操作都是无序的;前半句是指,线程内逻辑顺序表现为串行的语义,后半句指,指令重排序现象和工作内存与主内存同步延迟现象。
编译器或运行时环境为了优化程序性能而采取的对指令重新排序执行的一种手段。来看下面两个线程之间的交互,在单一线程中看,可以知道其操作是有序的,但是若是在线程1看线程2时,由于a--为非原子操作,故会导致输出的结果与预想结果不同。
public class test {
public static int a = 2;
public static void main(String[] args) throws InterruptedException{
Thread thread1 = new Thread(new Runnable() {
public void run() {
a--;
System.out.print(test.a);
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
a--;
System.out.print(test.a);
}
});
thread1.start();
thread2.start();
}
}