本地线程

深入了解Java内存模型

匿名 (未验证) 提交于 2019-12-02 21:53:52
本文主要是记录下自己学习的笔记,主要记录以下几个方面:    1、java内存模型的基础   2、重排序   3、顺序一致性   4、volatile内存语义   5、锁的内存语义   6、final域的内存语义   7、happens-before   8、双重检查锁定与延迟初始化   9、Java内存模型综述 一、Java内存模型的基础 1、并发编程模型的两个问题   在并发编程中,需要了解并会处理这两个关键问题:   1.1、线程之间如何通信?    通信是指线程之间以何种机制来交换信息 。在命令式编程中,线程之间的通信机制有两种: 共享内存和消息传递 。   a) 在 共享内存 的并发模型里, 线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。(重点)   b) 在 消息传递 的并发模型里, 线程之间没有公共状态,线程之间必须通过发送消息来显式进行通信。   1.2、线程之间如何同步?    同步是指程序中用于控制不同线程间操作发生相对顺序的机制。    在共享内存的并发模型里,同步是显示进行的 。因为程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。    在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。   知道并了解上面两个问题后,对java内存模型的了解,就打下了基础

Java并发编程:深入剖析ThreadLocal

匿名 (未验证) 提交于 2019-12-02 21:53:52
想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。   以下是本文目录大纲:   一.对ThreadLocal的理解   二.深入解析ThreadLocal类   三.ThreadLocal的应用场景   若有不正之处请多多谅解,并欢迎批评指正。   请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin0520/p/3920407.html   ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。   这句话从字面上看起来很容易理解,但是真正理解并不是那么容易。   我们还是先来看一个例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class ConnectionManager { private static null ; public static Connection openConnection() { if null ){

Java面试官最爱问的volatile关键字

匿名 (未验证) 提交于 2019-12-02 21:53:32
在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题。经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用volatile关键字作为切入点呢? 爱问volatile关键字的面试官,大多数情况下都是有一定功底的,因为volatile作为切入点,往底层走可以切入Java内存模型(JMM),往并发方向走又可接切入Java并发编程,当然,再深入追究,JVM的底层操作、字节码的操作、单例都可以牵扯出来。 所以说懂的人提问题都是有门道的。那么,先整体来看看volatile关键字都设计到哪些点:内存可见性(JMM特性)、原子性(JMM特性)、禁止指令重排、线程并发、与synchronized的区别……再往深层次挖,可能就涉及到字节码、JVM等。 不过值得庆幸的是,如果你已经学习了微信公众号“程序新视界”JVM系列的文章,上面的知识点已经不是什么问题了,权当是复习了。那么,下面就以面试官提问的形式,在不看答案的情况下,尝试回答,看看学习效果如何。夺命连环问,开始…… 被volatile修饰的共享变量,就具有了以下两点特性: 保证了不同线程对该变量操作的内存可见性; 禁止指令重排序; 回答的很好,点出了volatile关键字两大特性。针对该两大特性继续深入。 该问题涉及到Java内存模型(JVM

Java必备主流技术流程图

匿名 (未验证) 提交于 2019-12-02 21:52:03
1、Spring的生命周期 Spring作为当前java最流行性、最强大的轻量级容器框架,了解熟悉Spring的生命周期非常有必要 容器启动后,对bean进行初始化 按照bean的定义,注入属性 检测该对象是否实现xxxAware接口,并将相关的xxxAware实例注入给bean,如BeanNameAware等 以上步骤,bean对象已经正确构造,通过实现BeanPostProcessor接口,可以再进行一些自定义方法处理,如:postProcessBeforeInitialzation BeanPostProcessor的前置处理完成后,可以实现postConstruct,afterPropertiesSet,init-method等方法,增加我们自定义的逻辑。 通过实现BeanPostProcessor接口,进行postProcessAfterInitialzation后置处理 接着Bean准备好被使用啦 容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法 通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑 2、TCP三次握手,四次挥手 tcp的三次握手四次挥手是每个程序员都应该熟悉的。 三次握手 第一次握手(SYN=1,seq=x),发送完毕后,客户端进入SYN_SEND状态 第二次握手(SYN

(转)大厂常问到的14个Java面试题

匿名 (未验证) 提交于 2019-12-02 21:52:03
1. synchronized和reentrantlock异同 相同点 都实现了多线程同步和内存可见性语义 都是可重入锁 不同点 实现机制不同 synchronized通过java对象头锁标记和Monitor对象实现 reentrantlock通过CAS、ASQ(AbstractQueuedSynchronizer)和locksupport(用于阻塞和解除阻塞)实现 synchronized依赖jvm内存模型保证包含共享变量的多线程内存可见性 reentrantlock通过ASQ的volatile state保证包含共享变量的多线程内存可见性 使用方式不同 synchronized可以修饰实例方法(锁住实例对象)、静态方法(锁住类对象)、代码块(显示指定锁对象) reentrantlock显示调用trylock()/lock()方法,需要在finally块中释放锁 功能丰富程度不同 reentrantlock提供有限时间等候锁(设置过期时间)、可中断锁(lockInterruptibly)、condition(提供await、signal等方法)等丰富语义 reentrantlock提供公平锁和非公平锁实现 synchronized不可设置等待时间、不可被中断(interrupted) 2. concurrenthashmap为何读不用加锁 jdk1.7 1

Java线程本地存储ThreadLocal

匿名 (未验证) 提交于 2019-12-02 21:52:03
前言 无同步 Thread-Specific Storage 没有共享资源 ThreadLocal ThreadLocal 思维导图 线程安全 示意图 1. 用法 ThreadLocal ThreadLocal android.os.Looper.java ThreadLocal ThradlLocal UML类图 // /frameworks/base/core/java/android/os/Looper.java public class Looper { // ... // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 设置线程局部变量的值 sThreadLocal.set(new Looper(quitAllowed

Java中的ThreadLocal详解

匿名 (未验证) 提交于 2019-12-02 21:40:30
一、ThreadLocal简介   多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。ThreadLocal是除了加锁这种同步方式之外的一种保证一种规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。   ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题,如下图所示 二、ThreadLocal简单使用   下面的例子中,开启两个线程,在每个线程内部设置了本地变量的值,然后调用print方法打印当前本地变量的值。如果在打印之后调用本地变量的remove方法会删除本地内存中的变量,代码如下所示 1 package test; 2 3 public class ThreadLocalTest { 4 5 static ThreadLocal<String> localVar = new ThreadLocal<>(); 6 7 static void print(String str) { 8

JVM组成

大城市里の小女人 提交于 2019-12-02 21:22:28
Java虚拟机运行时数据区域主要包含了PC寄存器(程序计数器)、Java虚拟机栈、本地方法栈、Java堆、方法区以及运行时常量池。 Q3:运行时数据区中哪些区域是线程共享的?哪些是独享的? 在JVM运行时内存区域中,PC寄存器、虚拟机栈和本地方法栈是线程独享的。 而Java堆、方法区是线程共享的。但是值得注意的是,Java堆其实还未每一个线程单独分配了一块 TLAB 空间,这部分空间在分配时是线程独享的,在使用时是线程共享的。( TLAB介绍 ) Q4:堆和栈的区别是什么? 堆和栈(虚拟机栈)是完全不同的两块内存区域,一个是线程独享的,一个是线程共享的,二者之间最大的区别就是存储的内容不同: 堆中主要存放对象实例。 栈(局部变量表)中主要存放各种基本数据类型、对象的引用。 Q6:Java中的数组是存储在堆上还是栈上的? 在Java中,数组同样是一个对象,所以对象在内存中如何存放同样适用于数组; 所以,数组的实例是保存在堆中,而数组的引用是保存在栈上的。 Q7:Java中的对象创建有多少种方式? 1 . new 2. class.for().newInstance 3. Constructor 4. clone 5. 序列化 Q8:Java中对象创建的过程是怎么样的? 对于一个普通的Java对象的创建,大致过程如下: 1、虚拟机遇到new指令,到常量池定位到这个类的符号引用。 2

java面试题

匿名 (未验证) 提交于 2019-12-02 20:59:24
面向对象的三个特征 封装,继承,多态,这个应该是人人皆知,有时候也会加上抽象。 多态的好处 允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。主要有以下优点: 可替换性:多态对已存在代码具有可替换性 可扩充性:增加新的子类不影响已经存在的类结构 接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。 灵活性 简化性 代码中如何实现多态 实现多态主要有以下三种方式: 3. 同一类中进行方法重载 虚拟机是如何实现多态的 动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法。 接口的意义 接口的意义用三个词就可以概括:规范,扩展,回调。 抽象类的意义 抽象类的意义可以用三句话来概括: 为其他子类提供一个公共的类型 封装子类中重复定义的内容 定义抽象方法,子类虽然有不同的实现,但是定义时一致的 接口和抽象类的区别 比较 抽象类 接口 默认方法 抽象类可以有默认的方法实现 java 8之前,接口中不存在方法的实现. 实现方式 子类使用extends关键字来继承抽象类.如果子类不是抽象类,子类需要提供抽象类中所声明方法的实现. 子类使用implements来实现接口,需要提供接口中所有声明的实现. 构造器 抽象类中可以有构造器, 接口中不能

Java程序员必备的一些流程图

纵饮孤独 提交于 2019-12-02 20:13:30
转自: https://juejin.im/post/5d214639e51d4550bf1ae8df 前言: 整理了一些Java基础流程图/架构图,做一下笔记,大家一起学习。 1.spring的生命周期 Spring作为当前Java最流行、最强大的轻量级容器框架,了解熟悉spring的生命周期非常有必要; 首先容器启动后,对bean进行初始化 按照bean的定义,注入属性 检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean,如BeanNameAware等 以上步骤,bean对象已正确构造,通过实现BeanPostProcessor接口,可以再进行一些自定义方法处理。 如:postProcessBeforeInitialzation。 BeanPostProcessor的前置处理完成后,可以实现postConstruct,afterPropertiesSet,init-method等方法, 增加我们自定义的逻辑, 通过实现BeanPostProcessor接口,进行postProcessAfterInitialzation后置处理 接着Bean准备好被使用啦。 容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法 通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻 2