本地线程

【面试】如果你这样回答“什么是线程安全”,面试官都会对你刮目相看

十年热恋 提交于 2019-12-29 03:07:29
有读者跟我说,喜欢看我的文章,说很容易读,我确实在易读性上花费的心思不亚于在内容上。因为我不喜欢一上来就堆很多东西,而且把简单的东西搞得复杂人人都会,但是把复杂的东西讲的简单,确实需要非常多的思考。 不是线程的安全 面试官问:“什么是线程安全”,如果你不能很好的回答,那就请往下看吧。 论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的。切记望文生义。 同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。 目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。 在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。 假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子了。可能被其它线程修改了。 比如把你住的小区看作一个进程,小区里的道路/绿化等就属于公共区域。你拿1万块钱往地上一扔,就回家睡觉去了。睡醒后你打算去把它捡回来,发现钱已经不见了。可能被别人拿走了。 因为公共区域人来人往,你放的东西在没有看管措施时,一定是不安全的。内存中的情况亦然如此。 所以线程安全指的是

【面试】如果你这样回答“什么是线程安全”,面试官都会对你刮目相看

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-29 03:07:16
好文章来自: https://www.cnblogs.com/lixinjie/p/a-answer-about-thread-safety-in-a-interview.html#4279679 不是线程的安全 面试官问:“什么是线程安全”,如果你不能很好的回答,那就请往下看吧。 论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的。切记望文生义。 同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。 目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。 在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。 假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子了。可能被其它线程修改了。 比如把你住的小区看作一个进程,小区里的道路/绿化等就属于公共区域。你拿1万块钱往地上一扔,就回家睡觉去了。睡醒后你打算去把它捡回来,发现钱已经不见了。可能被别人拿走了。 因为公共区域人来人往,你放的东西在没有看管措施时,一定是不安全的。内存中的情况亦然如此。 所以线程安全指的是

ThreadLocal是什么?保证线程安全

和自甴很熟 提交于 2019-12-29 03:05:19
早在JDK 1.2的版本中就提供 Java .lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。   当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。   从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。   所以,在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及。 ThreadLocal的接口方法 ThreadLocal类接口很简单,只有4个方法,我们先来了解一下: void set(Object value)设置当前线程的线程局部变量的值。 public Object get()该方法返回当前线程所对应的线程局部变量。 public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。 protected Object initialValue

进程、线程及多线程的概念

若如初见. 提交于 2019-12-28 17:44:18
什么是进程、线程及多线程 进程 :一个应用程序开始运行,那么就会存在一个属于这个应用程序的进程。进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。也即是说:进程是指在系统中正在运行的一个应用程序。每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。 线程 :线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中可以有多个线程的,这时这个应用程序也可以称之为多线程程序。简而言之:程序执行靠线程,一个程序运行后至少有一个进程,一个进程中可以包含多个线程。 多线程 :就是一个程序中有多个线程在同时执行。 线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。 单线程程序 :就是有多个任务只能依次执行。当上一个任务执行结束后,下一个任务开始执行。如,多个人吃饭,但只有一双筷子,这样当一个人用筷子吃饭的时候,另一个人只能等上一个人吃完饭放下筷子,才能拿起筷子吃饭,这就是单线程; 多线程程序 :就是有多个任务可以同时执行。如,多个人吃饭,有多双筷子,这样多个人就能同时吃饭; 多线程的优点 : 1

一文带你了解那些不为人知的Java线程技巧与用法

别等时光非礼了梦想. 提交于 2019-12-28 02:41:01
萝卜白菜各有所爱。像我就喜欢Java。学无止境,这也是我喜欢它的一个原因。日常工作中你所用到的工具,通常都有些你从来没有了解过的东西,比方说某个方法或者是一些有趣的用法。比如说线程。没错,就是线程。或者确切说是Thread这个类。当我们在构建高可扩展性系统的时候,通常会面临各种各样的并发编程的问题,不过我们现在所要讲的可能会略有不同。 从本文中你将会看到线程提供的一些不太常用的方法及技术。不管你是初学者还是高级用户或者是Java专家,希望都能看一下哪些是你已经知道的,而哪些是刚了解的。如果你认为关于线程还有什么值得分享给大家的,希望能在下面积极回复。那我们就先开始吧。 初学者 1.线程名 程序中的每个线程都有一个名字,创建线程的时候会给它分配一个简单的Java字符串来作为线程名。默认的名字是”Thread-0″, “Thread-1″, “Thread-2″等等。现在有趣的事情来了——Thread提供了两种方式来设置线程名: 线程构造函数,下面是最简单的一个实现: class SuchThread extends Thread { Public void run() { System.out.println ("Hi Mom! " + getName()); } } SuchThread wow = new SuchThread(“much-name”); 线程名setter方法:

大厂面试经:说一下你们线上JVM是如何优化的?

这一生的挚爱 提交于 2019-12-27 15:08:17
JVM(Java虚拟机)简单来说就是运行Java代码的解释器,作为螺丝钉程序员JVM其实了解下就差不多啦,不懂JVM内部细节照样能写出优质的代码! 但是一到造火箭、飞机的场景(面试)不懂JVM的你,会被面试官虐的体无完肤,本期内容列举常见的JVM面试题: 说一JVM的内存模型是什么样子的? 什么时候对象可以被收回? 常见的垃圾回收器算法有哪些,各有什么优劣? 什么时候对象会进入老年代? 什么是空间分配担保策略? 如何优化减少Full GC? 面对这一大波JVM面试题,你真的Hold住吗?文章有点长,可以先收藏慢慢看。 JVM的内存模型是什么样子的? JVM内存模型可以大致可划分为 线程私有区域 和 共享区域 ,线程私有区域由虚拟机栈、本地方法栈、程序计数器组成,而共享区域由堆、元数据空间(方法区)组成。 再有人问你JVM的内存模型就回想下上面的图,但是知道JVM的内存模型的样子还是不行的,还要知道他们分别干什么的。 虚拟机栈/本地方法栈 当你碰到过 StackOverflowException 这个异常的时候,有没有思考下为什么会出现这样的异常呢?答案就在虚拟机栈中,JVM会为每个方法生成 栈帧 然后将 栈帧 压入虚拟机栈中。 举个粟子:假设JVM参数 -Xss 设置为 1m ,如果某个方法里面创建一个128kb的数组,那这个方法在同一个线程中只能递归4次,再递归第五次的时候就会报

java中的volatile变量

江枫思渺然 提交于 2019-12-27 05:18:39
同步与线程间通信: 通信 通信是指消息在两条线程之间传递。 既然要传递消息,那接收线程 和 发送线程之间必须要有个先后关系,此时就需要用到同步。通信和同步是相辅相成的。 同步 同步是指,控制多条线程之间的执行次序。 线程间通信方式: 共享内存 共享内存指的是多条线程共享同一片内存,发送者将消息写入内存,接收者从内存中读取消息,从而实现了消息的传递。 但这种方式有个弊端,即需要程序员来控制线程的同步,即线程的执行次序。 这种方式并没有真正地实现消息传递,只是从结果上来看就像是将消息从一条线程传递到了另一条线程。 消息传递 顾名思义,消息传递指的是发送线程直接将消息传递给接收线程。 由于执行次序由并发机制完成,因此不需要程序员添加额外的同步机制,但需要声明消息发送和接收的代码。 java多线程内存模型: 所有线程都共享一片内存,用于存储共享变量; 此外,每条线程都有各自的存储空间,存储各自的局部变量、方法参数、异常对象。 volatile的使用: public volatile boolean flag; 1)volatile在重排序(编译器、处理器在不改变程序执行结果的前提下,重新排列指令的执行顺序,以达到最佳的运行效率)中的使用: 在以下情况下,即使两行代码之间没有依赖关系,也不会发生重排序: volatile读 若volatile读操作的前一行为volatile读/写

一文带你彻底搞懂ThreadLocal

两盒软妹~` 提交于 2019-12-27 04:05:31
前言 共享变量一直是并发中的老大难问题,每个线程都对它有操作权,所以线程之间的同步很关键,锁也就应运而生。这里换一个思路,是否可以把共享变量私有化?即每个线程都拥有一份共享变量的本地副本,每个线程对应一个副本,同时对共享变量的操作也改为对属于自己的副本的操作,这样每个线程处理自己的本地变量,形成数据隔离。事实上这就是ThreadLocal了。 就线程同步而言,锁可以认为是时间换空间,ThreadLocal可以认为是空间换时间,其实个人觉得这么描述有点强行往同步靠的意思,专业的人干专业的事,同步这个还是就老老实实交给锁吧。 ThreadLocal最适合的是变量在线程间隔离而在方法或类间共享的场景。 ThreadLocal的应用场景 ThreadLocal在Spring中事务的应用 我们可能每天都在使用Spring写dao写service,真的是一个非常爽的框架.我们能用这么爽是因为Spring在底层把脏活儿累活儿全干了。在一个Service中我们可能要写很多个dao,如果多个dao都用不同的JDBC连接,很费时费力费资源不说,事务性就得不到保证了,因为我们知道事务需要在一个连接内才能得以实现。事务对应着连接,所以如果我们每个线程对应一个连接,也就能保证我们在一个service中很爽的叨叨叨了,Spring底层正是使用ThreadLocal对连接进行了封装,可劲儿叨吧你就

架构师-JVM(一)

两盒软妹~` 提交于 2019-12-26 23:41:33
参考资料: 官网 《深入理解Java虚拟机:JVM高级特性与最佳实践》 葛一鸣老师的《实战Java虚拟机》 一.类加载机制 编译过程:从源码到.class文件, javac Person.java --> Person.class Person.java -> 词法分析器-> tokens流 ->语法分析器->语法树/抽象语法树->语义分析器->注解抽象语法树->字节码生成器-> Person.class 文件 类文件(Class文件)格式: 官网定义 The class File formt JVM为什么可以做到跨平台,统一的class文件格式,详细可以参考官网文档 JVM想运行java程序,首先一步是先要将编译过得类文件加载到JVM内,想了解JVM,首先需要了解类加载机制上图表示类文件(class)到虚拟机的过程(类加载机制) 1 类加载机制过程 1.1 装载(Load) 查找和导入class文件 ( 1 ) 通过一个类的全限定名 ( 包名 + 类名 ) 获取定义此类的二机制字节流 ( 2 ) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据机构 ( 3 ) 在 JAVA 堆中生成一个代表这个类的java . lang . class 对象,作为对方法区中这些数据的访问入口 对于类的二机制流,JVM可以通过多种途径产生或获得,如: (1)

Java内存模型和JVM内存管理

柔情痞子 提交于 2019-12-26 22:38:25
Java内存模型 和 JVM内存管理 一、 Java内存模型: 1、 主内存和工作内存(即是本地内存):    Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程里面的变量有所不同步,它包含了实例字段、静态字段和构成数组对象的元素,但不包含局部变量和方法参数,因为后者是线程私有的,不会共享,当然不存在数据竞争问题(如果局部变量是一个reference引用类型,它引用的对象在Java堆中可被各个线程共享,但是reference引用本身在Java栈的局部变量表中,是线程私有的)。为了获得较高的执行效能,Java内存模型并没有限制执行引起使用处理器的特定寄存器或者缓存来和主内存进行交互,也没有限制即时编译器进行调整代码执行顺序这类优化措施。 JMM规定了所有的变量都存储在 主内存( Main Memory) 中。每个线程还有自己的 工作内存( Working Memory) ,线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量