1. 学习volatile的时候的一个样例
public class T {
boolean runing = true;
// int i=0;
void m(){
System.out.println("m start");
while (runing){
// try{
// TimeUnit.SECONDS.sleep(1);
// }catch (Exception e){
// e.printStackTrace();
// }
// i++;
}
System.out.println("m end");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
t.runing = false;
}
}
结果会:我一直以为,时间片轮询,迟早runing会刷新到主存,只是有延迟。而volatile会立即刷新到缓存。没想到结果是程序根本不会停止。
2.下面是我以前测试用的样例
public class T {
boolean runing = true;
// int i=0;
void m(){
System.out.println("m start");
while (runing){
// try{
// TimeUnit.SECONDS.sleep(1);
// }catch (Exception e){
// e.printStackTrace();
// }
// i++;
System.out.println("m");
}
System.out.println("m end");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
t.runing = false;
}
}
到了时间节点上,时间同步成功突然出现意外,程序结束了:
3. 更换程序,while中变成i++
public class T {
boolean runing = true;
int i=0;
void m(){
System.out.println("m start");
while (runing){
// try{
// TimeUnit.SECONDS.sleep(1);
// }catch (Exception e){
// e.printStackTrace();
// }
i++;
// System.out.println("m");
}
System.out.println("m end");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
t.runing = false;
}
}
结果程序不会结束了。
4. 再换程序,while中变成了sleep
public class T {
boolean runing = true;
// int i=0;
void m(){
System.out.println("m start");
while (runing){
try{
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
// i++;
// System.out.println("m");
}
System.out.println("m end");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
t.runing = false;
}
}
结果又会:
总结:为什么会产生这种奇怪的事件呢?
(1)第1段代码:因为里面没有干其他事,所有while不会让出时间片,也不会将主存中的runing标志刷新到自己的线程中。
(2)第2段代码:println的源码会调用如下代码段:
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
于是,println方法通过synchronized的可见性造成了上面的结果。
(3)第3段代码:理所当然也遇到了与第1段代码相似的经历
(4)第4段代码:调用sleep代码,CUP重新进入代码。发现变成了false(ps:纯属个人理解
)