本地线程

synchronized

梦想与她 提交于 2020-04-07 23:14:16
概念 是利用锁的机制来实现同步的。 互斥性: 即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。 可见性: 必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。 用法 修饰静态方法: //同步静态方法 public synchronized static void methodName() { try { TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+" aaa"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new Thread(SynchronizedDemo::methodName).start(); } } 当synchronized作用于静态方法时,其锁就是当前类的class对象锁

Volatile与Synchronized的区别

橙三吉。 提交于 2020-04-07 23:13:32
java线程的内存模型 java的线程内存模型中定义了每个线程都有一份自己的共享变量副本(本地内存),里面存放自己私有的数据,其他线程不能直接访问,而一些共享变量则存在主内存中,供所有线程访问。 上图中,如果线程A和线程B要进行通信,就要经过主内存,比如线程B要获取线程A修改后的共享变量的值,要经过下面两步: (1)、线程A修改自己的共享变量副本,并刷新到了主内存中。 (2)、线程B读取主内存中被A更新过的共享变量的值,同步到自己的共享变量副本中。 总结:在java内存模型中,共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。 java多线程中的三个特性:   原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。一个很经典的例子就是银行账户转账问题:比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。这2个操作必须要具备原子性才能保证不出现一些意外的问题。   可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。   有序性:就是程序执行的顺序按照代码的先后顺序执行。一般来说处理器为了提高程序运行效率,可能会对输入代码进行优化

jvm主内存与工作内存

白昼怎懂夜的黑 提交于 2020-04-07 19:49:08
一、jvm主内存与工作内存 首先,JVM将内存组织为主内存和工作内存两个部分。 主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。 1.所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共享的。 2.每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。 3.线程之间无法直接访问对方的工作内存中的变量,线程间变量的传递均需要通过主内存来完成。 JVM规范定义了线程对内存间交互操作: Lock(锁定):作用于主内存中的变量,把一个变量标识为一条线程独占的状态。 Read(读取):作用于主内存中的变量,把一个变量的值从主内存传输到线程的工作内存中。 Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。 Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。 Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。 Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中。 Write(写入)

【每周一讲】Java的ThreadLocal

喜你入骨 提交于 2020-04-07 05:04:38
1、初识她 她到底是谁? 姑且先看个例子。 public interface Counter { /** * 获取下一个序列值 * @return */ int getNextNum(); } public class SimpleCounter implements Counter { private int i = 0; @Override public int getNextNum() { return i++; } } public class TestCounter extends Thread { private Counter counter; public TestCounter(Counter counter) { this.counter = counter; } public void run() { for (int i = 0; i < 3; i++) { // ④每个线程打出3个序列值 System.out.println("thread[" + Thread.currentThread().getName() + "] --> count[" + counter.getNextNum() + "]"); } } /** * 测试多个线程处理共享对象的情况 * 使用ThreadLocal的方式,每个线程拥有各自独立的数据拷贝。即时同一个对象 *

java JVM内存相关

半世苍凉 提交于 2020-04-06 00:26:24
大家平时知道的java的内存分为栈和堆,一般new出来的对象都是在堆上的。这里用的是一般,也就是说在有些情况下可能不是分配在堆上。在一定的情况下对象也是可以分配到栈上的。首先看一下java JVM运行时的数据区: 图中的 方法区 和 堆 是所有线程共享的, 虚拟栈 , 本地方法栈 和 程序计数器 是线程私有的。也就是说虚拟栈,本地方法和程序计数器是线程隔离的。程序计数器是唯一不会出现oom的部分。 程序计数器 可以看成当前线程执行的字节码的行号暗示器。 虚拟机栈 和线程的生命周期是一样的,当线程执行的时候会创建一个栈帧,用于存放当前线程的方法出口,局部变量表,操作数栈,动态连接等信息。 本地方法栈 用于调用native方法使用。 堆 是所有线程共享的部分,用于存储创建的对象。 方法区 和堆一样都是所有线程共享的,方法区主要用于存放虚拟机加载的类的信息,常量,静态常量等信息。 除了运行时数据区外还有一部分内存是不受虚拟机管理的部分,这一部分就是直接内存,直接内存是直接在物理的memory分配,我们经常使用的 ByteBuffer. allocateDirect 就是直接在物理内存上分配的。但是在虚拟机里面会有这部分内存的引用,以便对这一部分内存进行管理。 本文内容参考《深入理解JAVA虚拟机》 来源: oschina 链接: https://my.oschina.net/u

ThreadLocal系列(三)-TransmittableThreadLocal的使用及原理解析

流过昼夜 提交于 2020-04-03 10:33:17
上一篇: ThreadLocal系列(二)-InheritableThreadLocal的使用及原理解析 一、基本使用 首先,TTL是用来解决ITL解决不了的问题而诞生的,所以TTL一定是支持父线程的本地变量传递给子线程这种基本操作的,ITL也可以做到,但是前面有讲过,ITL在线程池的模式下,就没办法再正确传递了,所以TTL做出的改进就是即便是在线程池模式下,也可以很好的将父线程本地变量传递下去,先来看个例子: // 需要注意的是,使用TTL的时候,要想传递的值不出问题,线程池必须得用TTL加一层代理(下面会讲这样做的目的) private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2)); private static ThreadLocal tl = new TransmittableThreadLocal<>(); //这里采用TTL的实现 public static void main(String[] args) { new Thread(() -> { String mainThreadName = "main_01"; tl.set(1); executorService.execute(() -> {

java中volatile关键字的含义

人盡茶涼 提交于 2020-03-31 08:05:46
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。 synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块。 volatile 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一 执行环境——jdk版本:jdk1.6.0_31 ,内存 :3G cpu:x86 2.4G public class Counter { public static int count = 0; public static void inc() { //这里延迟1毫秒,使得结果明显 try { Thread.sleep(1); } catch (InterruptedException e) { } count++; } public

JVM-内存模型

血红的双手。 提交于 2020-03-30 19:30:43
https://www.cnblogs.com/aishangJava/p/9541920.html 原创好记性不如烂笔头_ 最后发布于2019-02-16 10:42:10 阅读数 22616 收藏 展开 运行时数据区域 程序计数器:线程私有;记录指令执行的位置;这里不会出现OutOfMemoryError 虚拟机栈:线程私有;生命周期和线程一致;存储局部变量表、操作数栈、动态链接、方法出口等信息。(局部变量表:存放了编译期可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址);会出现的异常:1、StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度;2、OutOfMemoryError:如果虚拟机栈可以动态扩展,而扩展时无法申请到足够的内存。) 本地方法栈:线程私有;为虚拟机使用到的 Native 方法服务。也会有 StackOverflowError 和 OutOfMemoryError 异常。 堆:线程共享;JVM 所管理的内存中最大的一块区域,主要是存放对象实例和数组;会有OutOfMemoryError:如果堆中没有内存完成实例分配,并且堆也无法再扩展时,抛出该异常。 方法区:线程共享

Java面试常见知识点总结(一)

|▌冷眼眸甩不掉的悲伤 提交于 2020-03-30 16:00:55
1.sleep()和wait(): Java中的多线程是一种 抢占式 的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。 ● 共同点 : (1) 他们都是在 多线程 的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。 (2) wait()和sleep()都可以通过 interrupt() 方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。 如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。 需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。 ● 不同点 : (1) 每个对象都有一个锁来控制同步访问。 Synchronized 关键字可以和对象的锁交互

并发2-Synchronized

爷,独闯天下 提交于 2020-03-30 12:52:55
一、Synchronized的概念 是利用锁的机制来实现同步的。 锁机制有如下两种特性: 互斥性: 即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。 可见性: 必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。 二、Synchronized的使用 修饰静态方法    //修饰静态方法 public static synchronized void print() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"runing"); }    修饰非静态方法    //修饰非静态方法 public synchronized void print1() { try { TimeUnit.SECONDS.sleep(1