前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多线程之线程可见性synchronized

多线程之线程可见性synchronized

原创
作者头像
开源日记
修改2021-01-19 10:33:21
3310
修改2021-01-19 10:33:21
举报
文章被收录于专栏:JVMGC

synchronized的规定

  • 线程解锁前,必须把共享变量刷新到主内存
  • 线程加锁前将清空工作内存共享变量的值,需要从主存中获取共享变量的值。

加锁(synchronized 同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性。我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且还希望确保当一个线程修改了对象状态后,其他线程能够看到该变化。而线程的同步恰恰也能够实现这一点。

内置锁可以用于确保某个线程以一种可预测的方式来查看另一个线程的执行结果。为了确保所有的线程都能看到共享变量的最新值,可以在所有执行读操作或写操作的线程上加上同一把锁。下图示例了同步的可见性保证。

img
img

当线程 A 执行某个同步代码块时,线程 B 随后进入由同一个锁保护的同步代码块,这种情况下可以保证,当锁被释放前,A 看到的所有变量值(锁释放前,A 看到的变量包括 y 和 x)在 B 获得同一个锁后同样可以由 B 看到。换句话说,当线程 B 执行由锁保护的同步代码块时,可以看到线程 A 之前在同一个锁保护的同步代码块中的所有操作结果。如果在线程 A unlock M 之后,线程 B 才进入 lock M,那么线程 B 都可以看到线程 A unlock M 之前的操作,可以得到 i=1,j=1。如果在线程 B unlock M 之后,线程 A 才进入 lock M,那么线程 B 就不一定能看到线程 A 中的操作,因此 j 的值就不一定是 1。

synchronized线程可见性安全案例

代码语言:txt
复制
package com.keytech.task;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class SynchronizedTestOne {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Rumenzz r=new Rumenzz();
        //线程1
        executorService.execute(()->{
              r.setAge(200);
        });
        //线程2
        executorService.execute(()->{
            System.out.println(r.getAge());
        });

        executorService.shutdown();
    }
}


class Rumenzz{
    private Integer age=0;

    public synchronized Integer getAge() {
        return age;
    }

    public synchronized void setAge(Integer age) {
        this.age = age;
    }
}

以上代码是线程安全的,输出0200,因为线程1和线程2的执行顺序不一样。为了保证结果的一致性,需要控制线程的执行顺序。

代码语言:txt
复制
package com.keytech.task;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @className: SynchronizedTestOne
 * @description: TODO 类描述
 * @author: mac
 * @date: 2021/1/1
 **/
public class SynchronizedTestOne {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Rumenzz r=new Rumenzz();
        CountDownLatch c=new CountDownLatch(1);

        executorService.execute(()->{
            try {
                c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(r.getAge());


        });
        executorService.execute(()->{
            try {
                Thread.sleep(5000);
                c.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r.setAge(200);
        });

        //关闭线程池
        executorService.shutdown();
    }
}


class Rumenzz{
    private Integer age=0;

    public synchronized Integer getAge() {
        return age;
    }

    public synchronized void setAge(Integer age) {
        this.age = age;
    }
}

线程安全输出200

wx.jpg
wx.jpg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • synchronized的规定
  • synchronized线程可见性安全案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档