请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

老师,关于synchronized关键字

public class ThreadSafeCache {
    int result;

    /**
     * 用synchronized修饰就有可见性,不修饰没有可见性
     */
    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadSafeCache threadSafeCache = new ThreadSafeCache();
        for (int i = 0; i < 8; i++) {
            new Thread(() -> {
                int x = 0;
                while (threadSafeCache.getResult() < 100) {
                    x++;
                    //System.out.println();//加上有可见性,不加没有可见性
                }
                System.out.println(x);
            }).start();
        }
        Thread.sleep(1000);
        threadSafeCache.setResult(200);
    }
}

对于这段代码,我有两个问题:

问题一:

为什么加上System.out.println(),就有可见性,程序就可以终止?不加,就无法终止

https://img1.sycdn.imooc.com/szimg/662612c90967666b12860482.jpg

问题二:

在不加System.out.println()的情况下,在getResult()方法加上synchronized就有可见性,程序就可以终止,这是为什么呢?按理说读取值result,和线程安不安全应该说没有关系呀,又不是修改值

https://img1.sycdn.imooc.com/szimg/662613c1099942d509580334.jpg


我的思考:

我怀疑和synchronized有关,毕竟System.out.println()也加了synchronized关键字。我在网上找到了如下解释:

https://img1.sycdn.imooc.com/szimg/66261552093db06e12280084.jpg


请老师解答一下我心中的疑惑


正在回答 回答被采纳积分+3

2回答

Alfred_li 2024-04-26 11:23:28

在不加System.out.println()的情况下,在getResult()方法加上synchronized就有可见性,程序就可以终止,这是为什么呢?按理说读取值result,和线程安不安全应该说没有关系呀,又不是修改值

这就是同步关键字的作用,加了synchronized,线程会强制从主存读数据

0 回复 有任何疑惑可以回复我~
Alfred_li 2024-04-26 11:22:41

为什么加上System.out.println(),就有可见性,程序就可以终止?不加,就无法终止

for (int i = 0; i < 8; i++) {
            new Thread(() -> {
                int x = 0;
                while (threadSafeCache.getResult() < 100) {
                    x++;
                    //System.out.println();//加上有可见性,不加没有可见性
                }
                System.out.println(x);
            }).start();
        }

你的这个代码里边开启动了8个线程
随后在main方法里设置result为200,
main线程和你启动的8个子线程之前可以使用不同的cpu内核和cpu缓存,所以main写了result为200,你的8个子线程不是立即就能感知到的,
你加了System.out.println(x);
这里边有同步关键字,会强制读主存的数据,就读到了main线程的最新数据

0 回复 有任何疑惑可以回复我~
  • 提问者 相信光变成光 #1
    那我就有新的疑问了,老师。main线程在缓存中更改的值,并没有刷新到主存。其他8个子线程如何读取最新值呢?
    回复 有任何疑惑可以回复我~ 2024-04-26 11:58:37
  • 提问者 相信光变成光 #2
    老师,看到我的回复了吗
    回复 有任何疑惑可以回复我~ 2024-05-03 14:28:04
  • Alfred_li 回复 提问者 相信光变成光 #3
    没加同步时:main线程在缓存中更改的值,没有立即刷新回主存,会有一个写buffer,这个写buffer满了才会刷会主存,
    所以可以理解为,不做同步操作的话,写回的时间会有延迟(也可能立即写回,比如正好写buffer满了)
    加了同步时:也就是System.out.println(x)的锁,加锁的语义是从主存读数据到工作内存,解锁的语义是把数据从工作内存写会主存,所以不同线程间可以通过同步感知到数据变化
    回复 有任何疑惑可以回复我~ 2024-05-13 23:11:34
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信