本地线程

Java并发编程之volatile关键字

*爱你&永不变心* 提交于 2020-01-12 17:01:56
  大概是因为项目、业务的原因,工作上几乎还没有使用过多线程相关的功能,相关知识差不多都忘了,所以最近补一下基础。   volatile用来修饰共享变量,volatile变量具有 synchronized 的可见性特性,但是不具备原子特性。volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。当成员变量发生变化时,强迫线程将变化值回写到共享内存。以保证在同一时刻,不同的线程看到该成员变量的值是一致的。   因为volatile关键字与Java的内存模型有关,所以先看一下Java内存模型里面的几个概念知识。    1、可见性    指多个线程访问同一个变量时,一个线程修改了该变量的值,其他线程立马可以看到该线程修改后的值。   如下图所示,每个线程都有自己的工作内存,线程访问共享变量时,会先将变量加载到工作内存(如工作内存未缓存该变量),然后对工作内存中的变量副本进行读写操作。假设多个线程同时访问a变量,线程1修改了工作内存中的a变量值,但没有刷新到主内存中,其他线程从主内存缓存的a变量值还是原来的旧值;或者线程1修改a变量的值后刷新到了主内存,但是其他线程工作内存中缓存了线程1修改之前的旧值,其他线程访问该变量时没有从主内存中重新获取,就会出现在多个线程中,同一共享变量的值不一致,即存在可见性问题。   在 Java 中 volatile

干货:Java并发编程系列之volatile(二)

a 夏天 提交于 2020-01-12 06:35:53
接上一篇《Java并发编程系列之synchronized(一)》,这是第二篇,说的是关于并发编程的volatile元素。 Java语言规范第三版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。 java 内存模型的核心是围绕着在并发过程中如何处理原子性、可见性、有序性这3个特性来展开的,它们是多线程编程的核心。 原子性(Atomicity): 是指一个操作是不可中断的,即使是多个线程同时执行的情况下,一个操作一旦开始,就不会被其它线程干扰。对于基本类型的读写操作基本都具有原子性的(在32位操作系统中 long 和 double 类型数据的读写不是原子性的,因为它们有64位)。 可见性(Visibility): 是指在多线程环境下,当一个线程修改了某一个共享变量的值,其它线程能够立刻知道这个修改。 有序性(Ordering): 是指程序的执行顺序是按照代码的先后顺序执行的;对于这句话如果在单线程中所有的操作都是有序的,但是在多线程环境下,一个线程的操作相对于另外一个线程的操作是无序的。 了解volatile关键字之前需要先了解下Java内存模型,java内存模型抽象示意图如下: Java内存模型 线程A和线程B之间若要通信的话, 必须经历下面两个步骤 : (1

线程三大特性以及Volatile、ThreadLocal

≯℡__Kan透↙ 提交于 2020-01-12 04:26:14
线程三大特性 多线程有三大特性,原子性、可见性、有序性。 原子性: 即单次或者单组操作要么全部执行(执行的过程不会被任何因素打断)要么就都不执行。 可见性: 即当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 有序性: 程序执行的顺序按照代码的先后顺序执行。 简单来说,原子性保证数据的一致性,是线程安全的一部分,可见性保证多线程之间共享变量的变化能够及时被其它线程发现,有序性是指在一般情况下处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但它保证程序最终执行结果和代码顺序执行的结果是一致的。 重排序对单线程并不会产生任何影响,但在多线程情况下需要考虑。 Volatile Volatile关键字的作用是修饰变量使其在多个线程之间可见,Volatile保证可见性,但是Volatile不具备原子性。 简单来说,使用Volatile关键字可以解决线程之间共享变量可见性问题, 强制线程每次读取该值的时候都去“主内存”中取值。 volatile与synchronized区别? volatile 只能修饰变量,synchronized 可修饰代码块/函数/变量,前者是轻量级的。 volatile 只能保证可见性,不具备原子性,不能用来保证线程同步安全

JDK源码那些事儿之浅析Thread上篇

佐手、 提交于 2020-01-12 02:30:51
JAVA 中多线程的操作对于初学者而言是比较难理解的,其实联想到底层操作系统时我们可能会稍微明白些,对于程序而言最终都是硬件上运行二进制指令,然而,这些又太过底层,今天来看一下JAVA中的线程,浅析JDK源码中的Thread类,之后能帮助我们更好的处理线程问题 前言 JDK版本号:1.8.0_171 在Thread注释中可以看到大佬对其进行的解释: Thread就是程序中一个线程的执行. JVM 允许一个应用中多个线程并发执行 每个线程都有优先级.高优先级线程优先于低优先级线程执行 每个线程都可以(不可以)被标记为守护线程 当线程中的run()方法代码里面又创建了一个新的线程对象时,新创建的线程优先级和父线程优先级一样 当且仅当父线程为守护线程时,新创建的线程才会是守护线程 当JVM启动时,通常会有唯一的一个非守护线程(这一线程用于调用指定类的main()方法) JVM会持续执行线程直到下面某一个情况发生为止: 1.类运行时exit()方法被调用且安全机制允许此exit()方法的调用. 2.所有非守护类型的线程均已经终止,或者run()方法调用返回或者在run()方法外部抛出了一些可传播性的异常. 可以联想下JVM的启动过程,从main方法启动,可以自己写代码查看下线程情况 线程实现 Thread注释类上清楚的写明了线程的两种实现方式: 定义一个继承Thread类的子类

Linux线程(三)

假装没事ソ 提交于 2020-01-11 23:48:26
Linux线程(三) 一、互斥量 根据前面的分析,得到的结果不是我们想要的原因是–ticket操作不是原子操作,这个共享资源可能并发的切换大其他线程,导致有多个线程同时影响到这个共享资源,所以导致得到的结果不对。 1.解决方法(加锁—>Linux中叫这把锁为互斥量): 代码必须有互斥行为:当有一个执行流(有一个线程)进入临界区时,不允许其他线程进入该临界区 如果多个线程同时要求执行临界区的代码,并且临界区内没有线程在执行,那么只允许一个线程进入该临界区 如果线程不在临界区内执行,那么该线程不能阻止其他线程进入临界区 二、.互斥量的接口: 1.初始化互斥量 方法一:静态分配 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 方法二:动态分配 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 功能:初始化互斥量 参数:pthread_mutex_t *restrict mutex:要初始化的互斥量 const pthread_mutexattr_t *restrict attr:指定了新建互斥锁的属性。如果参数attr为NULL,则使用默认的互斥锁属性,默认属性为快速互斥锁 返回值

JVM-运行时数据区

你离开我真会死。 提交于 2020-01-11 07:10:07
   JVM在运行Java代码时,会把内存分为几个模块即数据区来使用,数据区的内容如下图所示: 1. PC寄存器:   JVM支持程序多线程执行。而操作系统的任务调度采用的是时间片轮询的抢占式调度方式,也就是说,某一个确定的时刻,一个处理器只能处理一条线程中的指令。因此,线程切换后如何恢复到原来正确的位置,便是通过每个线程各自的寄存器来实现的。在各线程中寄存器独立,互不干扰。   如果线程执行的方法不是native的,那PC寄存器保存的就是Java虚拟机正在执行的字节码指令的地址,如果该方法是native的,那寄存器的值就是undefined(null),此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 2. JAVA虚拟机栈:   java虚拟机栈也是Java线程私有的,它的生命周期与线程一样,用于存储栈帧,主要包括两部分,方法中的局部变量和方法执行过程中产生的中间结果。每一个方法从调用直到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。   因为除了栈帧的出栈和入栈之外,Java 虚拟机栈不会再受其他因素的影响,所以栈帧可以在堆中分配,Java 虚拟机栈所使用的内存不需要保证是连续的。   JVM规范允许VM Stack要么是一个固定大小,要么动态扩展来满足要求。如果JVM栈是一个固定的大小

详解JVM内存管理与垃圾回收机制1 - 内存管理

感情迁移 提交于 2020-01-10 06:44:48
Java应用程序是运行在JVM上的,得益于JVM的内存管理和垃圾收集机制,开发人员的效率得到了显著提升,也不容易出现内存溢出和泄漏问题。但正是因为开发人员把内存的控制权交给了JVM,一旦出现内存方面的问题,如果不了解JVM的工作原理,将很难排查错误。本文将从理论角度介绍虚拟机的内存管理和垃圾回收机制,算是入门级的文章,希望对大家的日常开发有所助益。 一、内存管理 也许大家都有过这样的经历,在启动时通过-Xmx或者-XX:MaxPermSize这样的参数来显式的设置应用的堆(Heap)和永久代(Permgen)的内存大小,但为什么不直接设置JVM所占内存的大小,而要分别去设置不同的区域?JVM所管理的内存被分成多少区域?每个区域有什么作用?如何来管理这些区域? 1.1 运行时数据区 JVM在执行Java程序时会把其所管理的内存划分成多个不同的数据区域,每个区域的创建时间、销毁时间以及用途都各不相同。比如有的内存区域是所有线程共享的,而有的内存区域是线程隔离的。线程隔离的区域就会随着线程的启动和结束而创建和销毁。JVM所管理的内存将会包含以下几个运行时数据区域,如下图的上半部分所示。 Method Area (方法区) 方法区是所有线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。在Java虚拟机规范中,方法区属于堆的一个逻辑部分

java笔记整理

我与影子孤独终老i 提交于 2020-01-10 03:48:31
基本概念 操作系统中 heap 和 stack 的区别 什么是基于注解的切面实现 什么是 对象/关系 映射集成模块 什么是 Java 的反射机制 什么是 ACID BS与CS的联系与区别 Cookie 和 Session的区别 fail-fast 与 fail-safe 机制有什么区别 get 和 post请求的区别 Interface 与 abstract 类的区别 IOC的优点是什么 IO 和 NIO的区别,NIO优点 Java 8 / Java 7 为我们提供了什么新功能 什么是竞态条件? 举个例子说明。 JRE、JDK、JVM 及 JIT 之间有什么不同 MVC的各个部分都有那些技术来实现?如何实现? RPC 通信和 RMI 区别 什么是 Web Service(Web服务) JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 WEB容器主要有哪些功能? 并请列出一些常见的WEB容器名字。 一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制 简单说说你了解的类加载器。是否实现过类加载器 解释一下什么叫AOP(面向切面编程) 请简述 Servlet 的生命周期及其相关的方法 请简述一下 Ajax 的原理及实现步骤 简单描述Struts的主要功能 什么是 N 层架构 什么是CORBA?用途是什么 什么是Java虚拟机

java中volatile关键字的含义

为君一笑 提交于 2020-01-09 20:30:16
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。 synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块。 volatile 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新值。volatile很容易被误用,用来进行原子性操作。 下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一 public class Counter { public static int count = 0; public static void inc() { //这里延迟1毫秒,使得结果明显 try { Thread.sleep(1); } catch (InterruptedException e) { } count++; } public static void

Synchronized、Threadlocal、Volatile

感情迁移 提交于 2020-01-09 14:38:28
synchronized: synchronized叫做同步锁,操作起来方便,只需要在一个方法或把需要同步的代码块包装在它内部,那么这段代码就是同步的了,所有线程对这块区域的代码访问必须先持有锁才能进入,否则则拦截在外面等待正在持有锁的线程处理完毕再获取锁进入正因为它基于这种阻塞的策略,所以它的性能不太好,但是由于操作上的优势, 只需要简单的声明一下即可,而且被它声明的代码块也是具有操作的原子性。 threadlocal (本地单机) 用来提供线程内的局部变量,这样每个线程都自己管理自己的局部变量,别的线程操作的数据不会对我产生影响,互不影响 就是把变量分成很多个拷贝,每个线程拥有一个。这里没有所谓的最后的结果,每个线程单独操作自己的变量,和其他的变量没关系,互不干扰 ThreadLocalMap类的定义是在ThreadLocal类中,真正的引用却是在Thread类中。同时,ThreadLocalMap中用于存储数据的entry定义,它是一个Map,他的key是ThreadLocal实例对象。 1、JVM利用设置ThreadLocalMap的Key为弱引用,来避免内存泄露。 2、JVM利用调用remove、get、set方法的时候,回收弱引用 3、当ThreadLocal存储很多Key为null的Entry的时候,而不再去调用remove、get、set方法,那么将导致内存泄漏 4