synchronized

synchronized底层语义原理

南笙酒味 提交于 2020-01-15 07:36:11
synchronized底层语义原理 ​ Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现, 无论是显式同步(有明确的 monitorenter 和 monitorexit 指令,即同步代码块)还是隐式同步都是如此。在 Java 语言中,同步用的最多的地方可能是被 synchronized 修饰的同步方法。同步方法 并不是由 monitorenter 和 monitorexit 指令来实现同步的,而是由方法调用指令读取运行时常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现的,关于这点,稍后详细分析。下面先来了解一个概念Java对象头,这对深入理解synchronized实现原理非常关键。 理解Java对象头和monitor 在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。如下: 实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。 填充数据:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这点了解即可。 而对于顶部,则是Java头对象,它实现synchronized的锁对象的基础,这点我们重点分析它,一般而言,synchronized使用的锁对象是存储在Java对象头里的

线程安全的原子性、可见性与有序性

本秂侑毒 提交于 2020-01-15 04:16:36
原子性: 一个或多个操作在CPU执行过程中不被中断的特性称之为原子性 。线程中执行的操作要么全部执行,要么全部不执行。 Java内存模型中的read、load、assign、use、store和write都可以保证原子性的操作(如果对Java内存模型不熟悉,可以参考我的这篇博文 Java内存模型 ),一般基本数据类型访问读写都是原子性的(long和double的非原子性协议例外,但是基本也不会发生) 如果应用场景需要一个更大范围的原子性保证,我们可以直接使用synchronized关键字,在synchronized块之间的操作也具有原子性。 可见性: 可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。 Java内存模型是通过变量修改之后同步回主内存,在变量读取之前从主内存刷新变量值来实现可见性的。如果一个普通变量在多线程中运行的话,往往不能保证可见性,多个线程都是从主内存中获取变量,这时多个线程并不会先等待某一个线程修改完变量之后,写回主内存,再从主内存获取最新的变量值。 如果要保证可见性的话,我们可以使用volatile关键字,具体原理可以参考我的这篇博文 Java的volatile关键字 ,当然除了volatile关键字之外,synchronized和final关键字也能实现可见性

JAVA进阶27(多线程/02)

▼魔方 西西 提交于 2020-01-15 03:30:47
1、线程同步 并发:同一个对象多个线程同步操作 1 package cn.Thread_demo; 2 3 /** 4 * @Classname SynBlockTest01 5 * @Description TODO 6 * @Date 2019-5-13 12:16 7 * @Created by Administrator 8 */ 9 public class SynBlockTest01 { 10 public static void main(String[] args) { 11 //一份资源 12 SynWeb12306 web = new SynWeb12306(); 13 //多个代理 14 new Thread(web, "张三").start(); 15 new Thread(web, "张四").start(); 16 new Thread(web, "张五").start(); 17 } 18 } 19 20 class SynWeb12306 implements Runnable { 21 //票数 22 private int ticketNums = 10; 23 private boolean flag = true; 24 25 @Override 26 public void run() { 27 while (flag) { 28 try

单例模式

我是研究僧i 提交于 2020-01-15 00:27:55
单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 注意: 1、单例类只能有一个实例。 2、单例类必须自己创建自己的唯一实例。 3、单例类必须给所有其他对象提供这一实例。 介绍 意图: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 主要解决: 一个全局使用的类频繁地创建与销毁。 何时使用: 当您想控制实例数目,节省系统资源的时候。 如何解决: 判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 关键代码: 构造函数是私有的。 应用实例: 1、一个班级只有一个班主任。 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。 优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 2、避免对资源的多重占用(比如写文件操作)。 缺点:

005多线程Thread

旧巷老猫 提交于 2020-01-14 21:58:07
多线程Thread 多进程概述 进程 多线程 线程调度 线程调度概述 线程优先级 设置对象优先级 线程控制:其他方法 线程睡眠sleep 线程加入 join(): 线程礼让,暂停当前线程,执行其他线程 后台线程 中断线程 线程的生命周期 实现多线程 1.继承Thread类 线程名称 获取线程名称 设置线程名称:2种 2.实现Runnable接口(常用) 概述 实现 线程安全问题 实现卖电影票案例(不安全) 方式1:继承Thread类 方式2:实现Runnable接口 问题分析:同票和负数票 同步(synchronized) 同步概述 同步方法 同步代码块 买票同步代码块 同步方法 买票同步方法 方法1 方法2 方法3:静态方法锁 银行存钱案例 Lock锁(JDK5之后) Lock锁卖票案例 线程死锁 死锁问题及其代码 死锁案例 方法1 方法2: 线程间通信 线程间通信概述 等待/唤醒机制 生产消费:加入等待唤醒机制,加入判断** 方法1(更好): 方法2: 优化生产消费问题 多生产者,多消费者的问题。烤鸭生产一只消费一只 Condition等待/唤醒机制 优化生产消费问题 线程组ThreadGroup 概述 获取线程组,名字 修改线程组 线程池 概述 Callable接口:创建线程3 1.求和案例 匿名内部类方式使用多线程 定时器 循环一次 循环调用 案例

【设计模式篇】单例模式

喜夏-厌秋 提交于 2020-01-14 21:48:36
01 单例模式     单例模式,只有一个实例存在于整个JVM中,保证只有一个实例,并可以被外界访问。它是一种常用的设计模式之一。实现单例模式 的方法有很多种,然而需要考虑包括线程安全在内的一些因素。以下列举了几种典型的实现方法。 02 实现及问题 方法一:懒汉式实现   【懒汉式】私有化构造函数,创建静态方法,提供单例引用,延迟加载。  重大缺陷:线程不安全, 线程A希望能够使用Singleton 实例 ,于是第一次调用静态方法getInstance(),发现此时singleton==null,准备创建实例,突然CPU发生时间片切换,线程B也希望 调用 该实例,此时A并未创建,因此singleton==null,B创建Singleton实例,执行完成后,线程A继续执行,因为已经判断过singleto n= =null,所以也创建了一个实例对象。 最终导致单例失败。 1 /** 2 * 懒汉式 写法1 3 * @author Administrator 4 * 5 */ 6 public class Singleton { 7 private Singleton(){ 8 9 } 10 private static Singleton singleton=null; 11 //静态工厂方法 12 public static Singleton getInstance(){ 13

Java最新面试题

99封情书 提交于 2020-01-14 19:17:37
2019最新整理JAVA面试题附答案 作者:Jack 包含的模块: 本文分为十九个模块,分别是:Java 基础、容器、多线程、反射、对象拷贝、Java Web 、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM 如下图所示: 共包含 208 道面试题,本文的宗旨是为读者朋友们整理一份详实而又权威的面试清单 ==================================================== 一. Java 基础模块 1.JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。 JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。 具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。 2.== 和 equals 的区别是什么

ConcurrentHashMap源码解析 JDK8

*爱你&永不变心* 提交于 2020-01-14 17:33:54
一、简介 上篇文章 详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理。 首先在看本文之前,希望对HashMap有一个详细的了解。不然看直接看ConcurrentHashMap的源码还是有些费劲的。 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTable虽然保证了线程安全性,但是其是通过给每个方法加Synchronized关键字达到的同步目的。但是都知道Synchronized在竞争激烈的多线程并发环境中,在性能上的表现是非常不如人意的。那在高并发环境中HashMap如何保证线程安全而又不浪费太多性能呢?答案就是Java J.U.C并发包中的ConcurrentHashMap。 依然开局一张图。JDK8中的ConcurrentHashMap数据结构。 呃呵,和HashMap的结构是一样的,没错在数据结构层面,ConcurrentHashMap和HashMap是完全一样的。有了这个基础继续往下看。 二、历史版本 ConcurrentHashMap的历史版本大致分界线在JDK8。也就是可以分为JDK8和JDK8以前版本。 数据结构的区别 在JDK8之前HashMap没有引入红黑树,同样的ConcurrentHashMap也没有引入红黑树

Java多线程编程(三)——volatile详解

穿精又带淫゛_ 提交于 2020-01-14 14:37:26
volatile 关键字和synchronized一样都能够保证线程的同步。 Java语言规范第三版中对volatile的定义如下: java编程语言允许线程 访问共享变量 ,为了确保共享变量能被准确和 一致 的更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,java线程 内存模型 确保所有线程看到这个变量的值是一致的。 volatile 被称为 轻量级 的 synchronized。 同时,它比synchronized的使用和执行成本会更低,因为它不会引起线程上下文的切换和调度。 一、volatile的特性 补充: 1. Java内存模型 (Java Memory Model, JMM ) JMM是由Java虚拟机规范定义的,用来屏蔽掉Java程序在各种不同的硬件和操作系统对内存的访问的差异,这样就可以实现java程序在各种不同的平台上都能达到内存访问的一致性。 在Java中,Java 堆内存 是存在数据共享的,这些共享数据的通信就是通过JMM来控制的。 JMM决定一个线程对共享数据的写入何时对另一个线程可见。 JMM是一个抽象的结构,它定义了 线程和主内存的关系 : 线程之间的 共享变量 存储在 主内存(Main Memory) 中 每一个线程都有一个私有的 本地内存(Local

Java: Do all mutable variables need to be volatile when using locks?

余生颓废 提交于 2020-01-14 13:51:30
问题 Does the following variable, x, need to be volatile? Or does the manipulation within a utils.concurrent lock perform the same function as a synchronized block (ensuring it's written to memory, and not stored in cpu cache)? myMethod(){ myLock.lock(); x++; myLock.unlock(); } 回答1: Such variables only need to be volatile if they're accessed elsewhere without a lock. For example, as a fast read-only access to a size variable. The lock methods do serve the same purpose as a synchronized block. See