本地线程

ThreadLocal学习(一)

丶灬走出姿态 提交于 2020-02-02 03:24:21
Java:ThreadLocal有什么用呢? ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。ThreadLocal可以用来解决多线程程序的并发问题,ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。 ThreadLocal的应用场景? 在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。这种情况下可以将 类变量 放到ThreadLocal类型的对象中,使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。最常见的ThreadLocal使用场景为用来解决数据库连接、Session管理等。在下面会例举几个场景。 ThreadLocal类中的方法:(JDK5版本之后支持泛型)

第十二章 并发编程 学习笔记

十年热恋 提交于 2020-02-01 18:03:16
第十二章 并发编程 进程是程序级并发,线程是函数级并发。 三种基本的构造并发程序的方法: 进程: 每个逻辑控制流是个一个进程,由内核进行调度和维护。 I/O 多路复用: 应用程序在一个进程的上下文中显式地调度他们自己的逻辑流。 线程: 运行在单一进程上下文中的逻辑流,由内核进行调度。 12.1 基于进程的并发编程 构造并发程序最简单的方法就是 用进程。 使用大家都很熟悉的函数例如: fork exec waitpid 关于在父、子进程间共享状态信息:共享文件表,但不共享用户地址空间。 进程又独立的地址空间既是优点又是缺点: 优点:防止虚拟存储器被错误覆盖 缺点:开销高,共享状态信息才需要IPC机制 12.2 基于I/O多路复用的并发编程 就是使用select函数要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。 select函数处理类型为fd_set的集合,也叫做 描述符集合。 select函数有两个输入:一个称为 读集合 的描述符集合和该妒忌和该读集合的基数(n)(实际上是任何描述符集合的最大基数)。select函数会一直阻塞,直到读集合中至少有一个描述符准备好可以读。当且仅当一个从该描述符读取一个字节的请求不会阻塞时,描述符K就表示准备好可以读了。 作为一个副作用,select修改了参数fdset指向的fd_set,指明读集合中一个称为准备好集合的子集

了解进程线程、同步异步、阻塞非阻塞、并发并行

守給你的承諾、 提交于 2020-02-01 17:49:59
基本概念 1 进程和线程 进程(Process): 是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。 线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。 线程(Thread): 是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。 进程和线程的区别 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。 线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间

线程---操作系统内存模型、java内存模型、线程可见性问题、 指令重排序、Happens-before规则

送分小仙女□ 提交于 2020-02-01 14:38:43
操作系统内存模型 L1、L2是每个CPU自己的高速缓存 L3是CPU之间共享的缓存 L1和L2的缓存命中率均约为80% 达到L3缓存数据占比4%左右 Java内存模型 每个线程有自己的工作内存 工作内存包含线程本地局部变量和主内存的副本拷贝 线程之间的共享变量通过主内存在各线程间同步 线程可见性问题 package day0201 ; public class ThreadSafe { private static int a = 0 ; public static void main ( String [ ] args ) throws Exception { Thread threadA = new Thread ( ( ) - > { System . out . println ( "threadA" + Thread . currentThread ( ) . getName ( ) + "a=" + a ) ; a = 1 ; System . out . println ( "threadA" + Thread . currentThread ( ) . getName ( ) + "a=" + a ) ; } ) ; Thread threadB = new Thread ( ( ) - > { System . out . println ( "threadB"

这一次,终于系统的学习了 JVM 内存结构

时光总嘲笑我的痴心妄想 提交于 2020-02-01 02:37:33
这一次,终于系统的学习了 JVM 内存结构 原创平头哥的技术博文 最后发布于2019-11-05 11:15:20 阅读数 5652 收藏 展开 最近在看《 JAVA并发编程实践 》这本书,里面涉及到了 Java 内存模型,通过 Java 内存模型顺理成章的来到的 JVM 内存结构,关于 JVM 内存结构的认知还停留在上大学那会的课堂上,一直没有系统的学习这一块的知识,所以这一次我把《 深入理解Java虚拟机JVM高级特性与最佳实践 》、《 Java虚拟机规范 Java SE 8版 》这两本书中关于 JVM 内存结构的部分都看了一遍,算是对 JVM 内存结构有了新的认识。JVM 内存结构是指:Java 虚拟机定义了若干种程序运行期间会使用的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁,另一些则与线程一一对应,随着线程的开始而创建,随着线程的结束而销毁。具体的运行时数据区如下图所示: 在 Java 虚拟机规范中,定义了五种运行时数据区,分别是 Java 堆、方法区、虚拟机栈、本地方法区、程序计数器,其中 Java 堆和方法区是线程共享的。接下来就具体看看这 五种运行时数据区。 Java 堆(Heap) Java 堆是所有线程共享的一块内存区域,它在虚拟机启动时 就会被创建,并且单个 JVM 进程有且仅有一个 Java 堆。Java 堆是用来存放对象实例及数组

java 线程之间是如何通信的

安稳与你 提交于 2020-02-01 01:06:27
java线程之间的通信方式总共有 8 种,分别是 volatile、synchronized、interrupt、wait、notify、notifyAll、join、管道输入/输出 , 我们一个一个的来说明! 1.volatile 线程会将内存中的数据,拷贝到各自的本地内存中( 这里的本地内存指的是 cpu cache ( 比如 CPU 的一级缓存、二级缓存等 ),寄存器)。当某个变量被 volatile 修饰并且发生改变时,volatile 变量底层会通过 lock前缀的指令,将该变量写会主存,同时利用 缓存一致性协议,促使其他线程的本地变量的数据无效,从而再次直接从主存读取数据。 代码演示: java 如何优雅的停止一个线程 2.synchronized monitor可以理解为一个同步工具,成功则获得了对象的锁,失败,则进入同步队列进行等待 代码演示: java 如何优雅的停止一个线程 3. interrupt 代码演示: java 如何优雅的停止一个线程 4. wait、notify、notifyAll 代码演示: /** * @author shengjk1 * @date 2019/8/29 */ /* 等待/通知的经典范式 */ public class WaitNotify { static boolean flag = true; static Object

JVM高频面试题

风流意气都作罢 提交于 2020-01-31 23:56:56
1、 类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,它们的执行顺序 先静态、先父后子。 先静态:父静态 > 子静态 优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数 一个类的实例化过程: 1、父类中的static代码块,当前类的static 2、顺序执行父类的普通代码块 3、父类的构造函数 4、子类普通代码块 5、子类(当前类)的构造函数,按顺序执行 6、子类方法的执行 2、 JVM内存分配 3、 Java 8的内存分代改进 从永久代到元空间,在小范围自动扩展永生代避免溢出 4、 JVM垃圾回收机制,何时触发MinorGC等操作  分代垃圾回收机制:不同的对象生命周期不同。把不同生命周期的对象放在不同代上,不同代上采用最合适它的垃圾回收方式进行回收。  JVM中共划分为三个代:年轻代、年老代和持久代。年轻代:存放所有新生成的对象;年老代:在年轻代中经历了N次垃圾回收仍然存活的对象,将被放到年老代中,故都是一些生命周期较长的对象;持久代:用于存放静态文件,如Java类、方法等。新生代的垃圾收集器命名为“minor gc”,老生代的GC命名为”Full GC 或者Major GC”.其中用System.gc()强制执行的是Full GC 判断对象是否需要回收的方法有两种: 1.引用计数 当某对象的引用数为0时,便可以进行垃圾收集。 2

多线程面试60题超详解

久未见 提交于 2020-01-31 09:24:54
多线程面试60题 1.多线程有什么用? 2.线程和进程的区别是什么? 3.Java 实现线程有哪几种方式? 4.启动线程方法 start()和 run()有什么区别? 5.怎么终止一个线程? 6.一个线程的生命周期有哪几种状态?它们之间如何流转的? 7.线程中的 wait()和 sleep()方法有什么区别? 8.多线程同步有哪几种方法? 9.什么是死锁?如何避免死锁? 10.多线程之间如何进行通信? 11、线程怎样拿到返回结果? 12、violatile 关键字的作用? 13、新建 T1、T2、T3 三个线程,如何保证它们按顺序执行? 14、怎么控制同一时间只有 3 个线程运行? 15、为什么要使用线程池? 16、常用的几种线程池并讲讲其中的工作原理。 什么是线程池? 线程池的好处 如何提交线程 submit 和 execute 分别有什么区别呢? 如何关闭线程池es.shutdown()? 17、线程池启动线程 submit()和 execute()方法有什么不同? 18、CyclicBarrier 和 CountDownLatch 的区别? 19、什么是活锁、饥饿、无锁、死锁? 20、什么是原子性、可见性、有序性? 21、什么是守护线程?有什么用? 什么是守护线程? 22、一个线程运行时发生异常会怎样? 23、线程 yield()方法有什么用? 24、什么是重入锁? 25

C# 多线程 Mutex Monitor Lock

僤鯓⒐⒋嵵緔 提交于 2020-01-31 03:27:33
lock关键字 lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下: Object thisLock = new Object(); lock (thisLock) { // Critical code section } lock 确保当一个线程位于代码的临界区时, 另一个 线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 lock 调用块开始位置的 Enter 和块结束位置的 Exit 。 通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this) 、 lock (typeof (MyType)) 和 lock ("myLock") 违反此准则: 如果实例可以被公共访问,将出现 lock (this) 问题。 如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。 由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。 最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。 下例使用线程和 lock 。只要 lock 语句存在,语句块就是临界区并且 balance 永远不会是负数。 /

基元线程同步构造之 Mutes(互斥体)

核能气质少年 提交于 2020-01-30 07:12:52
  互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex))。   互斥体禁止多个线程同时进入受保护的代码“ 临界区 ”(critical section)。    因此,在任意时刻,只有一个线程被允许进入这样的代码保护区。任何线程在进入 临界区 之前,必须获取(acquire)与此区域相关联的互斥体的所有权。如果已有另一线程拥有了 临界区 的互斥体,其他线程就不能再进入其中。这些线程必须等待,直到当前的属 主线程 释放(release)该互斥体。什么时候需要使用互斥体呢?互斥体用于保护共享的易变代码,也就是,全局或静态数据。这样的数据必须通过互斥体进行保护,以防止它们在多个线程同时访问时损坏。    互斥体(mutex)代表一个互斥的锁。它的工作方式和AutoResetEvent(或者计数为1的Semaphore)相似,因为所有这三种构造一次都只释放一个正在等待的线程, 实例化一个mutex时,就默认释放了一个正在等待的线程,类似于初始化了一个 new AutoResetEvent(true) 。下面展示了Mutex类的样子:   public sealed class Mutex:WaitHandle{ public Mutex(); public void ReleaseMutex(); }    互斥体有一些而外的逻辑在里面