并发与高并发-线程安全性-可见性

前言

乍看可见性,不明白它的意思。联想到线程,意思就是一个线程对主内存的修改及时的被另一个线程观察到,即为可见性

那么既然有可见性,会不会存在不可见性呢?

答案是肯定的,导致线程不可见的原因是什么呢?

有三个原因:

(1)线程交叉执行。

(2)重排序结合线程交叉执行。

(3)共享变量更新后的值没有在工作内存与主存间及时更新。

主体内容

一、这里的可见性涉及到synchronized,顺便了解一些一下JMM对synchronized的两条规定:

  1.线程解锁前,必须把共享变量的最新值刷新到主内存中

  2.线程加锁时,将清空工作内存中存储的共享变量的值,从而使用共享变量时,必须从主内存中重新读取最新的值。(注意:解锁和加锁,是指同一把锁)

二、同时涉及到volatile。

  1.volatile通过内存屏障和禁止重排序优化来实现内存可见性。

  (1)对volatile变量进行的操作时,会在写操作后加入一条store屏障指令,将本地内存中的共享变量值刷新到主内存。

  (2)对volatile变量进行的操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量。

  这样就能保证线程读写的都是最新的值。

  简单的通过两张图分别看一下读写操作时的过程。

      volatile写插入内存屏障示意图

        volatile读插入内存屏障示意图

原文地址:https://www.cnblogs.com/jmy520/p/12046052.html

时间: 2024-10-30 03:13:45

并发与高并发-线程安全性-可见性的相关文章

java并发编程实战笔记-线程安全性

什么是线程安全性 线程安全性定义中最核心的概念就是:**正确性**.我们将单线程的正确性近似 定义为"所见即所知",当多个线程访问这个类的时候,始终能表现出正确的行为, 那么这个类就是线程安全类. 当多个线程访问某个类时,不管运行时环境采用什么调度方式或者这些线程将如何 交替运行,并且调用代码时,不需要额外的同步,就可以产生正确的结果.这个类 就是线程安全类. 在线程安全类上执行任何串行或者并行的操作都不会使对象处于无效状态. 可重入代码:就是这段代码,和其他代码不存在共享状态,只包含

并发、高并发、集群的含义?

并发:多个用户同时向服务器发出请求,服务器会开启多个线程,每个线程服务一个用户 高并发:当用户量达到成千上万,会导致服务器资源不再充足,最终使服务器内存溢出 集群:可以解决高并发问题  集群将一个应用拷贝多份,搭在多台服务器(机器),多台服务器构成一个集群 原文地址:https://www.cnblogs.com/codeXi/p/11429871.html

【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)

声明 特此声明:文中有关支付宝账户的说明,只是用来举例,实际支付宝账户要比文中描述的复杂的多.也与文中描述的完全不同. 前言 很多网友留言说:在编写多线程并发程序时,我明明对共享资源加锁了啊?为什么还是出问题呢?问题到底出在哪里呢?其实,我想说的是:你的加锁姿势正确吗?你真的会使用锁吗?错误的加锁方式不但不能解决并发问题,而且还会带来各种诡异的Bug问题,有时难以复现! 在上一篇<[高并发]如何使用互斥锁解决多线程的原子性问题?这次终于明白了!>一文中,我们知道在并发编程中,不能使用多把锁保护

并发与高并发(八)-线程安全性-原子性-synchronized

前言 闲暇时刻,谈一下曾经在多线程教程中接触的同步锁synchronized,相当于复习一遍吧. 主要介绍 synchronized:依赖JVM Lock:依赖特殊的CPU指令,代码实现,ReetrantLock 主体内容 一.那么我们主要先讲解一下关于同步锁synchronized的作用范围. 1.修饰代码块:作用范围-大括号括起来的代码,作用于调用这个代码块的对象,如果不同对象调用该代码块就不会同步. 2.修饰方法:作用范围-整个方法,作用于调用这个方法的对象. 3.修饰静态方法:作用范围-

[高并发]Java高并发编程系列开山篇--线程实现

ava是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相同的内存空间进行并发读写操作.这可能是在单线程程序中从来不会遇到的问题.其中的一些错误也未必会在单CPU机器上出现,因为两个线程从来不会得到真正的并行执行.然而,更现代的计算机伴随着多核CPU的出现,也就意味着不同的线程能被不同的CPU核得到真正意义的并行执行. 那么,要开始Java并发之路,就要开始

Java并发和高并发学习总结(四)- J.U.C之工具类

1.总览 CountDownLatch允许一个或多个线程等待某些操作完成 Semaphore Java版本的信号量实现 CyclicBarrier 一种辅助性的同步结构,允许多个线程等待到达某个屏障 Exchanger 在线程间交换数据的一种手段 2.CountDownLatch 当一个或多个线程需要等待其他线程完成操作时,就可以使用CountDownLatch了,当然,最简单的你也可以使用join方法 2.1.join public class JoinTest { public static

并发与高并发-并发模拟代码

一.CountDownLatch 1.背景: (1)countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier.Semaphore.concurrentHashMap和BlockingQueue. (2)存在于java.util.cucurrent包下. 2.概念 (1)countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行. (2)是通过一个计数器来实现的,计数器的初始值是线程的数量.每当一个线程执行完毕后,计数器的值就-1

并发与高并发(十三)J.U.C之AQS

前言 什么是AQS,是AbstractQueuedSynchronizer类的简称.J.U.C大大提高了并发的性能,而AQS又是J.U.S的核心. 主体概要 J.U.C之AQS介绍 J.U.C之AQS-CountDownLatch J.U.C之AQS-Semaphore J.U.C之AQS-CyclicBarrier J.U.C之AQS-ReentrantLock与锁 主体内容 总结 原文地址:https://www.cnblogs.com/jmy520/p/12337891.html

并发与高并发(十四)J.U.C组件拓展

前言 J.U.C的拓展组件有哪些?分别在什么场景下使用?如何使用? 主体概要 J.U.C-FutureTask J.U.C-ForkJoin J.U.C-ForkJoin 主体内容 一.J.U.C-FutureTask 1.这里要介绍的第一个组件是FutureTask,这个组件是J.U.C里面的,但它不是AQS的子类.这个类对线程结果的处理值得我们去学习.在学习Java多线程的时候,一定接触过Thread,Runnable,一种是直接继承Thread,另一种就是实现Runnable,这两种方式有