Java内存模型

Java内存模型(JMM)主要目标是定义多线程的情况下线程访问变量的规则

JMM规定线程之间的共享变量存储在主内存中,每个线程都有一个本地内存(工作内存),本地内存存储了共享变量的副本。

关于线程安全

  • 什么是线程安全问题?

    多个线程同时共享同一个全局变量的操作时候,可能会受到其他线程的干扰,导致数据脏读。(数据一致性问题)

  • 如何解决线程安全问题?

    核心思想:在同一时刻,只能有一个线程执行。

    通过加锁使线程更加安全,也使程序的执行效率更低。

  • 衡量线程安全的3个要素:

    • 原子性:一个操作或者多个操作要么全部执行,要么都不执行
    • 可见性:多个线程访问同一变量,一个线程修改了变量的值,其他线程可以立即看到修改的值
    • 有序性:程序按照代码的顺序先后执行(与指令重排有关)

Volatile关键字

volatile是一种轻量级的同步机制,可以保证可见性【及时将修改的变量刷新到主内存中】,但不能保证原子性,并且禁止重排序。

volatile在多线程下的适用场景:一写多读

volatile如何保证内存可见性?

当一个线程对volatile修饰的变量进行写操作时,该线程中的本地内存的变量会被立刻刷新到主内存中。

当一个线程对volatile修饰的变量进行读操作时,该线程直接读取主内存的变量。

volatile能否保证线程安全?

不能,保证线程安全需要同时具备原子性,可见性和有序性。而volatile只能保证可见性和有序性,无法保证原子性。

Synchronized锁

核心思想:在多线程执行同一个方法时,只有获取到锁,才能进入方法里面执行

使用方式:

  • 修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象
  • 修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象
  • 修饰一个静态的方法:其作用的范围是整个方法,作用的对象是这个类的所有对象
  • 修饰一个代码块:被修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码块,作用的对象是调用这个代码块的对象

重入锁

当一个线程已经获取到锁后,再次请求该锁,就可直接获取。(锁的传递性)

Synchronized属于可重入锁

Lock锁

自动挡Synchronized:Java关键字,在代码执行完或程序抛出异常自动释放锁

手动挡Lock:可以高度控制获取锁,释放锁的过程,扩展性极强

死锁

同步中嵌套同步,导致锁无法释放。

乐观锁与悲观锁

锁可以从不同的角度分类,乐观锁和悲观锁是其中一种。

乐观锁和悲观锁并不是锁的具体实现,而是并发控制的两种策略,或者说是抽象。

乐观锁(适合多读场景)

  • 思想:认为不会发生线程冲突

  • 执行流程,先读取数据,然后在更新前检查在读取至更新这段时间数据是否被修改

    • 未修改:直接更新数据
    • 已修改:重新读取,再次提交更新(或者放弃操作)

为什么乐观锁适合多读场景?

乐观锁是一种更新前的检查机制,相对于悲观锁来说在多读场景下可以减少锁的性能开销,对于多写场景,乐观锁会一直进入已修改,重新读取,再次提交的循环,反而带来更多的资源消耗。

悲观锁(适合多写场景)

  • 思想:认为一定会发生线程冲突

  • 执行流程:读取数据的时候上锁(其他用户无法读取),直到本次数据更新完成才会释放锁。在多写场景下,能保证较高的数据一致性。

【总的来说,乐观锁回滚重试,悲观锁阻塞事务】

线程安全&Java内存模型的更多相关文章

  1. Java 线程 — JMM Java内存模型

    JMM Java Memory Model,Java内存模型,属于语言级的内存模型 并发编程中存在的问题: 如何通信:用于线程之间交换信息.两种方式:共享内存,消息传递 如何同步:用于控制不同线程间操 ...

  2. 【Java线程】Java内存模型总结

    学习资料:http://www.infoq.com/cn/articles/Java-memory-model-1 Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态, ...

  3. (转)【Java线程】Java内存模型总结

    Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变 ...

  4. 深入理解Java虚拟机(第三版)-13.Java内存模型与线程

    13.Java内存模型与线程 1.Java内存模型 Java 内存模型的主要目的是定义程序中各种变量的访问规则,即关注在虚拟机中把变量值存储到主内存和从内存中取出变量值的底层细节 该变量指的是 实例字 ...

  5. java内存模型和线程

    概述 多任务的处理在现在的计算机中可以说是"标配"了,在许多的情况下,让计算机同时做几件事情,不仅是因为计算机的运算能力的强大,还有一个重要的原因是:cpu的运算速度和计算机的存储 ...

  6. java内存模型与线程(转) good

    java内存模型与线程 参考 http://baike.baidu.com/view/8657411.htm http://developer.51cto.com/art/201309/410971_ ...

  7. JAVA内存模型与线程

    概述 由于计算机的运算速度和它的存储和通讯子系统的速度差距巨大,大部分时间都花在IO,网络和数据库上.为了压榨CPU的运算能力,需要并发.另外,优秀的并发程序对于提高服务器的TPS有重要的意义. 硬件 ...

  8. Java内存模型与Java线程实现原理

    硬件的效率与一致性 基于高速缓存的存储交互很好的解决了处理器和内存的速度矛盾,但是也为计算机系统带来了更高的复杂度,因为引入了一个新问题:缓存一致性. 在多处理器系统中,每个处理器都有自己的高速缓存, ...

  9. 深入理解JVM(6)——Java内存模型和线程

    Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...

随机推荐

  1. Centos7之LNMP环境编译安装

    Centos7之LNMP环境编译安装 一.系统环境准备 注:安装时间过长,只做参考!!!1.系统信息 [root@localhost ~]# uname -r 3.10.0-957.el7.x86_6 ...

  2. Centos7安装ftp服务

    本文介绍的ftp是可以使用匿名用户登录,且默认路径是根路径,私人使用非常方便,公开使用具有一定的风险,不安全. # .安装 yum install -y vsftpd # .配置 vim /etc/v ...

  3. python golang中grpc 使用示例代码详解

    python 1.使用前准备,安装这三个库 pip install grpcio pip install protobuf pip install grpcio_tools 2.建立一个proto文件 ...

  4. vue学习(十一) v-for使用的注意事项:2.2.0+之后的版本里,当在组件中使用v-for时,key是必须的,它是用来表示唯一身份的

    //html <div id="app"> <div> <label>id <input type="text" v- ...

  5. springboot(五)使用FastJson返回Json视图

    FastJson简介: fastJson是阿里巴巴旗下的一个开源项目之一,顾名思义它专门用来做快速操作Json的序列化与反序列化的组件.它是目前json解析最快的开源组件没有之一!在这之前jaskJs ...

  6. Python 3爬虫、数据清洗与可视化实战PDF高清完整版免费下载|百度云盘

    百度云盘:Python 3爬虫.数据清洗与可视化实战PDF高清完整版免费下载 提取码: 内容简介 <Python 3爬虫.数据清洗与可视化实战>是一本通过实战教初学者学习采集数据.清洗和组 ...

  7. SAS X option

    1. SAS X选项就是调用DOS命令. 例子: option noxwait;/*黑窗口执行完命令后自动关闭*/ %let path =.; %let filter=*.lst; X “ dir & ...

  8. 轻松应对并发问题,Newbe.Claptrap 框架中 State 和 Event 应该如何理解?

    Newbe.Claptrap 框架中 State 和 Event 应该如何理解?最近整理了一下项目的术语表.今天就谈谈什么是 Event 和 State. Newbe.Claptrap 是一个用于轻松 ...

  9. myBatis源码解析-缓存篇(2)

    上一章分析了mybatis的源码的日志模块,像我们经常说的mybatis一级缓存,二级缓存,缓存究竟在底层是怎样实现的.此次开始分析缓存模块 1. 源码位置,mybatis源码包位于org.apach ...

  10. Python File writelines() 方法

    概述 writelines() 方法用于向文件中写入一序列的字符串.高佣联盟 www.cgewang.com 这一序列字符串可以是由迭代对象产生的,如一个字符串列表. 换行需要制定换行符 \n. 语法 ...