问题来自于学习thinking in java的时候的一个示例,先上代码吧

public class StopThread {

    private static boolean stop = false;

    public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable(){
public void run() {
int i = 0;
while (!stop) {
i++;
}
}
}); t.start(); TimeUnit.SECONDS.sleep(1);
stop = true;
}
}

毫无疑问,这段代码会永远的执行下去,因为后台线程感觉不到主线程已经改变了stop,

然后我习惯性的在while循环中打印了下i(syso)

然后运行,发现程序在运行了一秒左右就停止了!!

我一脸懵逼,然后看了下syso的代码,发现有一段同步块

public void println(int x) {
synchronized (this) {
print(x);
newLine();
}
}

然后我也在代码里尝试着加了一个空的同步块,发现也会停止

public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
int i = 0; Object lock = new Object(); long start = System.nanoTime();
while (!stop) {
i++; synchronized (lock) {
// nothing
}
} long end = System.nanoTime();
Duration d = Duration.ofNanos(end - start);
System.out.println(d.toMillis() + "ms");
}
}); t.start(); TimeUnit.SECONDS.sleep(1);
stop = true;
}

运行结果是 1000ms

那么问题来了,synchronized 到底干了什么。。

按理说,synchronized 只会保证该同步块中的变量的可见性,发生变化后立即同步到主存,但是,stop变量并不在同步块中

实际上,JVM对于现代的机器做了最大程度的优化,也就是说,最大程度的保障了线程和主存之间的及时的同步,也就是相当于虚拟机尽可能的帮我们加了个volatile,但是,当CPU被一直占用的时候,同步就会出现不及时,也就出现了后台线程一直不结束的情况。

举个例子,在while循环中sleep一下,程序会很快的结束,sleep方法中并没有同步代码块

public void run() {
int i = 0;
long start = System.nanoTime();
while (!stop) {
i++; try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
}
} long end = System.nanoTime();
Duration d = Duration.ofNanos(end - start);
System.out.println(d.toMillis() + "ms");
}

再举个栗子,在while循环中做一些耗时但不耗CPU的操作,也会结束的很快,因为这个时候CPU空闲了,JVM就有机会尽快的将主存和栈变量同步

public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
int i = 0;
long start = System.nanoTime();
while (!stop) {
i++;
Object[] arr = new Object[1000000];
} long end = System.nanoTime();
Duration d = Duration.ofNanos(end - start);
System.out.println(d.toMillis() + "ms");
}
}); t.start(); TimeUnit.SECONDS.sleep(1);
stop = true;
}

关于synchronized 影响可见性的问题的更多相关文章

  1. synchronized的可见性理解

    之前的时候看<并发编程的艺术>,书中提到dcl写法的单例模式是有问题的,有可能会导致调用者得到一个创建了一半的对象,从而导致报错.修复办法是将单例对象的引用添加volatile进行修饰,禁 ...

  2. java synchronized实现可见性对比volatile

    问题: 大家可以先看看这个问题,看看这个是否有问题呢? 那里有问题呢? public class ThreadSafeCache { int result; public int getResult( ...

  3. Volatile和Synchronized对可见性和原子性的支持

    在学习并发编程的时候,遇见了volatile和synchronized关键字问题,volatile是可以保证可见性,但无法保证原子性,synchronized关键字由于其是加锁机制,肯定是可以保证原子 ...

  4. synchronized内存可见性理解

    一.背景 最近在看<Java并发编程实战>这本书,看到共享变量的可见性,其中说到"加锁的含义不仅仅局限于互斥行为,还包括内存可见性". 我对于内存可见性第一反应是vol ...

  5. synchronized实现可见性

    JMM关于synchronized的两条规定: 1)线程解锁前,必须把共享变量的最新值刷新到主内存中 2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值 ( ...

  6. java线程-synchronized实现可见性代码

    以下是一个普通线程代码: package com.Sychronized; public class SychronizedDemo { //共享变量 private boolean ready=fa ...

  7. volatile、Synchronized实现变量可见性的原理,volatile使用注意事项

    变量不可见的两个原因 Java每个线程工作都有一个工作空间,需要的变量都是从主存中加载进来的.Java内存模型如下(JMM): 线程访问一个共享的变量时,都需要先从主存中加载一个副本到自己的工作内存中 ...

  8. 1 Java线程的内存可见性

    Java内存的可见性 可见性: 一个线程对共享变量的修改,能够及时被其它线程看到 共享变量: 如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量 Java内存模型(JM ...

  9. 细说Java多线程之内存可见性

    编程这些实践的知识技能,每一次学习使用可能都会有新的认识 一.细说Java多线程之内存可见性(数据挣用)         1.共享变量在线程间的可见性                共享变量:如果一个 ...

随机推荐

  1. Spring中的JDBCTemplate

    src\dayday\JDBCTestTest package dayday;import com.sun.org.apache.xalan.internal.xsltc.compiler.Templ ...

  2. target和currentTarget的区别

    target在事件流的目标阶段:currentTarget在事件流的捕获,目标及冒泡阶段.只有当事件流处在目标阶段的时候,两个的指向才是一样的, 而当处于捕获和冒泡阶段的时候,target指向被单击的 ...

  3. CDH5X 安装oozie报错To enable Oozie web console install the Ext JS library.

    最近在CDH5.X 安装oozie 服务,服务安装完毕,访问oozie server ui,报如下错误: 页面提示: Oozie web console is disabled.To enable O ...

  4. Uncaught ReferenceError: WebForm_DoPostBackWithOptions is not defined

    环境:Asp.Net网站,Framework版本4.0,IIS版本7.0问题:按钮失效,下面是按钮代码: <a id="dnn_ctr1161_Login_Login_DNN_cmdL ...

  5. 学习笔记:CSS3的filter属性

    CSS3的filter属性 (版权归原作者所有) http://www.jianshu.com/p/ca7a2bdcc1e7/comments/4956985 filter: blur(5px); f ...

  6. 解决 WPF AllowsTransparency = true 和 Webbrowser 等控件显示冲突

    代码: public class FormsWebBrowser { Window _owner; FrameworkElement _placementTarget; Form _form; AxA ...

  7. Django1.3 创建项目

    经历了各种失败各种烦恼以后Django开发环境终于搭建好了! 系统环境:ubuntu12.04    Django版本1.3.1   Python版本 2.7.3 接下来就兴建一个项目练习一下 1.创 ...

  8. JAVA Web day02--- Android小白的第二天学习笔记

    CSS(美工部分知识,了解) 1. CSS概述 1.1.CSS是什么? * CSS 指层叠样式表 样式表:存储样式的地方 层叠:一层一层叠加 高大富有帅气人 1.2.CSS有什么作用? *CSS就是用 ...

  9. Runtime Complexity of .NET Generic Collection

    Runtime Complexity of .NET Generic Collection   I had to implement some data structures for my compu ...

  10. Swift 编程语言自己实践 -自己在Xcode6 动手写20140603

    Swift 是什么,大家都回去百度或者Google,有的甚至认为是Taylor Swift(她是我的偶像),但是如果今天在百度百科里搜索绝对没有说是Apple最新推出的编程语言,因为是在2014年6月 ...