线程同步的作用包含2个方面:
1.原子性:这里的原子性跟数据库事务的原子性相似,不论多个可变状态变量还是单个可变状态变量,要保证并发操作的正确性,必须保证每个线程拿到的数据都是正确的,不存在过期数据或者部分过期数据。最常见的违反原子性错误的情形是:"select-update"、"check-use"、"read-change-write",由于最终使用数据要依赖数据以前的状态,不是一个原子的操作,就容易因为线程执行时序的不同而导致结果不同。
2.可见性:可见性是指一个线程的数据状态对另一个线程是不是可见的,如果不可见,则A线程对共享数据的操作结果,B线程是拿不到的。
public class ShareStateTest {
public static boolean ready = false;
public static int num = 0;
public static void main(String[] args){
new Thread(){
@Override
public void run() {
while(true) {
while(!ready){
System.out.println(Thread.currentThread().getId() + "It's not ready! num = " + num);
}
System.out.println(Thread.currentThread().getId() + "It's ready! num=" + num);
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
while(!ready){
ready = true;
num = 2;
System.out.println("" + Thread.currentThread().getId() + " ready is true and num is " + num);
}
}
}
}.start();
}
}
这里涉及到多线程调试,我用的是IDEA,设置好断点,鼠标右键,出现DEBUG选择框,按下图配置就可以进行多线程调试,IEAD还可以设置进入断点的条件。
然后,开启DUBUG模式,可以看到线程不是并行执行的,而是受到线程调度器的调度,起初一直运行第一个线程,然后,过了几个时间片,开始运行第二个线程,这时ready已经被置为true了,但是第一个线程依然看不到ready的值变为true,又过了几轮的交替执行,才看到第一个线程打印了第二个while循环后边的输出,我想这是因为第二个线程将ready的值写回主内存需要时间吧!