本想今天覆习一下volatile的,结果在写demo时,怎么也达不到效果。还以为写错的呢。最后发现是 System.out.printlnr惹的祸。
我的demo如下:
定义一个变量控制线程的中断。
最初的demo是这样的:
class Test1{
//public volatile static int num =0;
public static int num =0;
public static void main(String[] args) {
new Thread(()->{
while (num==0){
System.out.println(Thread.currentThread().getName());
}
},"thredname --1").start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1;
System.out.println(num);
}
}
不成功后,又换成多线程
class Test1{
// public static int num =0;
public static void main(String[] args) {
test11 test11 = new test11();
for (int i = 0; i < 10; i++) {
new Thread(()->{
while (test11.num==0){
System.out.println(Thread.currentThread().getName());
}
},"thredname --"+i).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test11.num = 1;
System.out.println(test11.num);
}
}
class test11{
public int num =0;
}
妈耶,还是不行,啥情况?
于是百度volatile,也是这样的呢,还找视频了,也是这样啊?
突然弹幕说为啥多了一个sout就不行了?
我靠,惊醒梦中人。
注释掉果然是自己想要的结果了。
不过是为啥呢?又百度了(这个习惯有点不好,没有自己的思考就直接查原因,要改正)
原来这个pringtIn竟然是线程安全的
源码如下:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
咦,为啥加锁会是变量可见呢。这个在一个博客中是这么说的:
加锁的含义不仅仅局限于互斥行为,还包括内存可见性
-
JMM关于Synchronized的两条规定:
- 线程解锁前,必须把共享变量的最新值刷新到主内存中;
- 线程加锁时,讲清空工作内存中共享变量的值,从而使用共享变量是需要从主内存中重新读取最新的值(加锁与解锁需要统一把锁)
-
线程执行互斥锁代码的过程:
- 获得互斥锁
- 清空工作内存
- 从主内存拷贝最新变量副本到工作内存
- 执行代码块
- 将更改后的共享变量的值刷新到主内存中
- 释放互斥锁
ok ,找到原因。
总结:还是基础弱,还是要多看书,多练习。
附录: