前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个线程问题的记录

一个线程问题的记录

作者头像
DH镔
发布2019-12-19 22:44:18
3690
发布2019-12-19 22:44:18
举报

不阻塞

代码语言:javascript
复制
/**
 * @author donghaibin
 */
public class ThreadDemo {

    private static boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        newThread();
        running = false;
    }

    private static void newThread() {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (running) {
                    
                }
            }
        };
        thread.start();
    }
}

这里不阻塞的原因:main函数是程序的入口,先执行,不让出CPU子线程无法执行。当执行newThread()创建一个子线程时,running已经等于false。

阻塞

代码语言:javascript
复制
/**
 * @author donghaibin
 */
public class ThreadDemo {

    private static boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        newThread();
        Thread.sleep(100);
        running = false;
    }

    private static void newThread() {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (running) {
         
                }
            }
        };
        thread.start();
    }
}

这里原因和上面同理可得,主线程停止了100ms,让出了cpu执行子线程,running变量没有加volatile,无法保证可见性,当执行running = false时,对其他线程不可见。所以无法跳出while循环。

不阻塞

代码语言:javascript
复制
/**
 * @author donghaibin
 */
public class ThreadDemo {

    private static boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        newThread();
        Thread.sleep(100);
        running = false;
    }

    private static void newThread() {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (running) {
                    System.out.println("---");
                }
            }
        };
        thread.start();
    }
}

这里不阻塞的原因:

先看下System.out.println的源码

代码语言:javascript
复制
    /**
     * Prints an integer and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(int)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @param x  The <code>int</code> to be printed.
     */
    public void println(int x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

源码中存在synchronized

当线程释放一个锁时会强制性的将工作内存中之前所有的写操作都刷新到主内存中去,而获取一个锁则会强制性的加载可访问到的值到线程工作内存中来。虽然锁操作只对同步方法和同步代码块这一块起到作用,但是影响的却是线程执行操作所使用的所有字段。

所以执行println时,刷新了running

这里还存在一种可能:JVM优化,也叫作提升(hoisting)

https://hllvm-group.iteye.com/group/topic/34932#post-232535 https://github.com/sjsdfg/effective-java-3rd-chinese/blob/master/docs/notes/78.%20%E5%90%8C%E6%AD%A5%E8%AE%BF%E9%97%AE%E5%85%B1%E4%BA%AB%E7%9A%84%E5%8F%AF%E5%8F%98%E6%95%B0%E6%8D%AE.md

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档