专栏首页JVMGC多线程之线程可见性synchronized
原创

多线程之线程可见性synchronized

synchronized的规定

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

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

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

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线程可见性安全案例

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的执行顺序不一样。为了保证结果的一致性,需要控制线程的执行顺序。

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

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java多线程之可见性之volatile

    入门小站
  • 并发编程-06线程安全性之可见性 (synchronized + volatile)

    并发编程-06线程安全性之可见性 (synchronized + volatile)

    小小工匠
  • 多线程之内存可见性Volatile(一)

    从这篇博文开始,我们开始分享一些多线程的内容,毕竟在工作中,使用多线程比较多。多总结一下,终归没有坏处。这个系列的文章不会特别长,争取在3到5分钟之间结束,主要...

    程序猿小亮
  • 多线程(六)—–synchronized

    synchronized有三种方式来加锁,分别是: 1.修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁 2.修饰静态方法,作用于当前类对...

    全栈程序员站长
  • Java多线程之synchronized详解

    多个线程访问同一个资源时,需要对该资源上锁。即同时只允许一个线程访问该资源。任何线程要执行synchronized里的代码,都必须先拿到锁。synchroniz...

    用户1195962
  • Java多线程--对象的可见性

      最近在看《Java并发编程实战》,并发方面的知识,今天看到了对象的可见性,在这里分享一下。

    haoming1100
  • Java多线程的可见性与有序性

    如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。

    全菜工程师小辉
  • 008.多线程-synchronized锁

    为了解决线程安全问题, 我们的做法是:不要让多个线程同时对一个全局变量作写的操作。

    qubianzhong
  • 【多线程】synchronized基础

    本次的文章也是基本讲烂了的synchronized,希望我写的比别人写的更简单易懂,哈哈哈。其实有关多线程的知识点有很多,无论哪门语言都是这样,所以以后会穿插着...

    用户8902830
  • 详解Java多线程锁之synchronized

    synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。

    全菜工程师小辉
  • Java多线程中的内存可见性

    分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去。当发生对变量的修改时,会同步到主内存,主内存再同步到其他线程内存中去...

    zhangheng
  • 004. 线程安全之可见性问题

    山海散人
  • 【J2SE快速进阶】——多线程之synchronized

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • Java 多线程并发编程之 Synchronized 关键字

    现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的同步锁,同时,线程 B 也去调用 Test...

    哲洛不闹
  • Java多线程之synchronized关键字详解

    多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。

    魏晓蕾
  • 多线程二 synchronized的使用

    它的机制是手动加锁,自动释放锁。下面看一个例子,在异常的地方一定要处理异常,不然就会想下面代码中的线程1,会被释放掉。

    sleeping
  • 多线程编程学习十二(原子性、可见性与有序性)

    原子(atom)指化学反应不可再分的基本微粒,原子在化学反应中不可分割。原子操作指的是不可分割的整体,多线程的原子性指的是没有其他线程能够中断或检查正在原子操作...

    JMCui
  • Java多线程:线程属性

    喜欢天文的pony站长
  • 并发编程-05线程安全性之原子性【锁之synchronized】

    并发编程-06线程安全性之可见性 (synchronized + volatile)

    小小工匠

扫码关注云+社区

领取腾讯云代金券