本地线程

并发编程(四)—— ThreadLocal源码分析及内存泄露预防

眉间皱痕 提交于 2020-02-07 09:49:50
今天我们一起探讨下ThreadLocal的实现原理和源码分析。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。相信本文一定能让大家完全了解ThreadLocal。 ThreadLocal是什么?   ThreadLocal是啥?以前面试别人时就喜欢问这个,有些伙伴喜欢把它和线程同步机制混为一谈,事实上ThreadLocal与线程同步无关。ThreadLocal虽然提供了一种解决多线程环境下成员变量的问题,但是它并不是解决多线程共享变量的问题。那么ThreadLocal到底是什么呢?   ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的 局部变量 ,也许把它命名为ThreadLocalVariable更容易让人理解一些。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。   通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间

Java内存区域

霸气de小男生 提交于 2020-02-07 04:16:32
Java内存区域与OOM 文章目录 Java内存区域与OOM 引言 概述 内存区域 程序计数器 VM Stack虚拟机栈 Native Stack本地方法栈 Heap堆内存 方法区与常量池 Direct Memory直接内存 讲讲OOM 总结 引言 一句契合Java/C++使用者的话,“两者之间存在一堵由内存分配与GC技术筑建起来的高墙,墙里面的人想出去,墙外面的人却想进来”。 概述 Java有着自动的内存分配管理机制,也有自己独特的内存回收机制,只有熟练掌握这些知识,才能够真正地使用这门语言 内存区域 先上一个内存区域图: 如图,JAVA运行时内存区域分为 方法区(线程共享) 堆(线程共享) 虚拟机栈(线程私有) 本地方法栈(线程私有) 程序计数器(线程私有) 下面我们来讲讲这些内存区域所负责的工作。 程序计数器 JVM中的程序计数器与操作系统中的程序计数器功能是一致的,只不过操作系统的程序计数器记录的是下一条执行指令的地址,而JVM的程序计数器记录的是“当前”线程执行的字节码指令或者分支、循环、异常、线程恢复等功能的字节码支持。 程序计数器对不同方法的支持 Java method JNI 记录执行的字节码指令地址 Native方法这个计数器记录为空值 程序计数器是JVM中唯一不会出现OOM的地方。 VM Stack虚拟机栈 JVM中的虚拟机栈也是线程私有的

pthread_mutex_t

夙愿已清 提交于 2020-02-07 03:30:24
在Linux中使用线程 http://blog.csdn.net/jiajun2001/article/details/12624923 :LINUX就是这个范围作者 原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和本声明。否则将追究法律责 我并不假定你会使用Linux的线程,所以在这里就简单的介绍一下。如果你之前有过多线程方面的编程经验,完全可以忽略本文的内容,因为它非常的初级。 首先说明一下,在Linux编写多线程程序需要包含头文件pthread.h。也就是说你在任何采用多线程设计的程序中都会看到类似这样的代码: [cpp] view plain copy #include <pthread.h> 当然,进包含一个头文件是不能搞定线程的,还需要连接libpthread.so这个库,因此在程序连接阶段应该有类似这样的指令: gcc program.o -o program -lpthread 1. 第一个例子 在Linux下创建的线程的API接口是pthread_create(),它的完整定义是: [cpp] view plain copy int pthread_create(pthread_t * thread, const pthread_attr_t *attr, void *(*start_routine)( void*) void *arg)

java 笔记

房东的猫 提交于 2020-02-07 02:21:19
后台开发的过程中积累的关于java的杂记 架构 SSH框架 为什么要分层? 因为分层使代码变得清晰,容易写也容易阅读,更重要的是让代码扩展性更好,层与层之间的改动不会互相影响 各层的分工 dao——与数据库交互 service——处理业务逻辑,调用dao层方法 action——用来控制转发,接到请求交给service处理 dao是用于操作数据用的,service是为页面功能服务的,在service中对数据进行处理计算,然后返回数据结果到ACTION,而action则再对数据进一步处理,比如把list转成json,把两个service数据进行合并等,并发送到jsp页面显示。 并发相关 ReentrantLock 参考 Java多线程11:ReentrantLock的使用和Condition lock之后要自己unlock lock相比synchronized更加灵活,可以通过trylock判断锁是不是被占用了,在被占用的情况下可以忙其他事,而不是直接就阻塞了 lock持有的是对象监视器,也就是类似于syncronized(this){} ,但是需要注意这两者持有的对象监视器是不同的 lock配置Condition的signal和await可以实现syncronized的wait和notify来实现等待/通知模型,相比之下Condition更灵活

Java内存

試著忘記壹切 提交于 2020-02-06 16:06:36
Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区。 一,内存区域划分   1.线程共享区域:     (1)Java堆(对象实例),GC的主要区域,会出现OutOfMemoryError     (2)方法区(加载的类信息,常量,静态变量,即时编译器编译后的代码)会出现OutOfMemoryError   2.线程私有区域:     (1)虚拟机栈(操作数栈,动态链接,方法返回地址,局部变量)       用于支持虚拟机进行方法方法调用和方法执行的数据结构。生命周期与线程相同,每个方法执行时会创建一个栈帧并入栈,对于执行引擎,活动线程中,只有栈顶的栈帧是有效的,称为当前栈帧,所关联的方法称为当前方法。       如果申请的栈深度大于虚拟机允许的栈深度则抛出StackOutflowError       如果在动态扩展时,无法申请到足够的内存则抛出OutOfMemoryError       单线程:无论是栈空间太大,还是虚拟机内存太小,抛出的都是StackOutflowError       多线程:抛出OutOfMemoryError         局部变量表:是一组变量值存储空间

muduo库学习笔记十三:base库之ThreadLocalSingleton

扶醉桌前 提交于 2020-02-06 11:48:43
线程本地存储单例类 : 针对“每个结构”每个线程仅有一个线程本地存储类对象 t_value_:类型为T的指针是pod类型可以用__thread修饰,每个线程一份 deleter:Deleter类对象 instance():返回T引用 pointer():返回T指针 destructor():借助Deleter才能被调用 Deleter类:嵌套在ThreadLocalSingleton类中,借助于TSD实现线程本地存储机制 Show Me The Code : // Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H #define MUDUO_BASE_THREADLOCALSINGLETON_H #include <boost/noncopyable.hpp> #include <assert.h> #include <pthread.h> namespace muduo { template<typename T> class

吃透源码的每一个细节和设计原理--ThreadLocal

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-06 10:46:04
引言 ThreadLocal 是面试过程中非常高频的一个类,这类的复杂程度绝对是可以带出一系列连环炮的面试轰炸。biu biu biu ~~~~. 一直觉得自己对这个类很了解了,但是直到去看源码,接二连三的技术浮出水面(弱引用,避免内存溢出的操作,开放地址法解决hash 冲突,各种内部类的复杂的关系),看到你怀疑人生,直到根据代码一步一步的画图才最终理解(所以本篇文章会有大量的图)。 这里也给大家一个启示,面对复杂的事情的时候,实在被问题绕晕了,就画图吧,借助图可以让问题可视化,便于理解。 WAHT ThreadLocal 是一个线程的本地变量,也就意味着这个变量是线程独有的,是不能与其他线程共享的,这样就可以避免资源竞争带来的多线程的问题,这种解决多线程的安全问题和lock(这里的lock 指通过synchronized 或者Lock 等实现的锁) 是有本质的区别的: lock 的资源是多个线程共享的,所以访问的时候需要加锁。 ThreadLocal 是每个线程都有一个副本,是不需要加锁的。 lock 是通过时间换空间的做法。 ThreadLocal 是典型的通过空间换时间的做法。 当然他们的使用场景也是不同的,关键看你的资源是需要多线程之间共享的还是单线程内部共享的 使用 ThreadLocal 的使用是非常简单的,看下面的代码 看到这里是不是觉得特别简单?别高兴太早

java并发原理实战(16) --jdk8新增读写锁的升级—StampedLock

瘦欲@ 提交于 2020-02-06 01:21:30
文章目录 StampedLock有三种读/写模式:写、读、乐观读。 写。独占锁 读。共享锁 乐观读。方法tryOptimisticRead() 转换 转载: https://blog.csdn.net/panweiwei1994/article/details/78824505 StampedLock是JDK1.8新增的一个锁,是对读写锁ReentrantReadWriteLock的改进。前面已经学习了ReentrantReadWriteLock,我们了解到,在共享数据很大,且读操作远多于写操作的情况下,ReentrantReadWriteLock值得一试。但要注意的是,只有当前没有线程持有读锁或者写锁时才能获取到写锁,这可能会导致写线程发生饥饿现象,即读线程太多导致写线程迟迟竞争不到锁而一直处于等待状态。StampedLock可以解决这个问题,解决方法是如果在读的过程中发生了写操作,应该重新读而不是直接阻塞写线程。 StampedLock有三种读/写模式:写、读、乐观读。 写。独占锁 只有当前没有线程持有读锁或者写锁时才能获取到该锁。方法writeLock()返回一个可用于unlockWrite(long)释放锁的方法的戳记。tryWriteLock()提供不计时和定时的版本。 读。共享锁 如果当前没有线程持有写锁即可获取该锁,可以由多个线程获取到该锁。方法readLock(

jvm 虚拟机的组成部分

感情迁移 提交于 2020-02-05 00:24:12
1、 类加载子系统 :负责从文件系统或者网络中加载 Class 信息,加载的信息存放在 一块称之为方法区的内存空间 2、 方法区:存放类信息,常量信息,常量池信息,包括字符串字面量和数字常量等 3、Java 堆:在 java 虚拟机启动的时候建立 java 堆,他是 java 程序最主要的 内存工作区域,几乎所有的对象实例都存放在 java 堆中,堆空间是所有线程共享 的 4、 直接内存: java 的 NIO 库允许 java 程序使用直接内存,从而提高性能,通常 直接内存性能要优于 java 堆。读写频繁的场合可能会有限考虑 5、 栈:每个虚拟机线程都有一个私有的栈,一个线程的 java 栈在线程创建的时候 被创建, java 栈中保存着局部变量、方法参数、同时 java 的调用、返回值等 6、 本地方法栈:调用本地方法,本地方法一般是用 c 编写的 7、 垃圾回收系统:垃圾回收系统是 java 的核心,也是必不可少的, java 有一套 自己进行垃圾清理的机制,开发人员无需手工清理 8、pc 寄存器:寄存器也是每个线程私有的空间, java 虚拟机会为每个线程创建 pc 寄存器,在任意时刻,一个 java 线程总是在执行一个方法,这个方法被称为当前 方法,如果当前方法不是本地方法,则 pc 寄存器的值为 undefined ,寄存器存放 如当前环境指针,程序计数器,操作栈指针

JVM 完整深入解析

末鹿安然 提交于 2020-02-04 22:17:58
工作之余,想总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。Java虚拟机所管理的内存包括以下几个运行时数据区域,如图: 1、程序计数器:指向当前线程正在执行的字节码指令。线程私有的。 2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈帧就会出栈。 (1)栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接 a、局部变量表:包含了方法执行过程中的所有变量。局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部变量数组的大小。 b、返回值:如果有返回值的话,压入调用者栈帧中的操作数栈中,并且把PC的值指向 方法调用指令 后面的一条指令地址。 c、操作数栈:操作变量的内存模型。操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stacks项中)。操作数栈的的元素可以是任意Java类型,包括long和double,32位数据占用栈空间为1, 64 位数据占用2。方法刚开始执行的时候,栈是空的,当方法执行过程中