自旋

123 java锁synchronized相关内容

妖精的绣舞 提交于 2020-02-11 19:05:15
自旋锁:循环等待,不断尝试获取,成功后退出。 乐观锁: 修改数据时发现数据变化则重读数据并修改---假定不冲突 悲观锁:从读数据开始就加锁 -- 假定冲突 独占锁:一把用写,其他线程不能加锁。 共享锁:读,可以加读锁,但不能加写锁。 (不)可重入锁:已经获取锁的线程未释放前重新获取锁,是否阻塞。reentrantlock,synchronized 均可重入 公平锁,非公平锁:是否按顺序拿锁。 synchronized: 对非静态方法加锁this,静态方法加锁:class 可重入,独占锁,悲观锁 单线程内无意义的锁操作,触发jit后会出现锁消除 合并多个无意义的小锁为一个锁--锁粗化。jvm处理时触发jit优化。 实例锁的标记存储在对象头(class meta address、array length、markword)中 ;mark word(hashcode,threadid、lock record address、monitor address,forword address) 状态(unlocked、biased、light-weight lock,heavy-weight lock,marked for gc) 状态和存的值一一对应。 抢锁时:读取对象的mark word存入当前线程;cas操作mark word,新值 local record address(例:轻量级锁

synchronized介绍

我是研究僧i 提交于 2020-02-11 17:59:18
1、在多线程并发编程中synchronized一直被称为重量级锁,但是随着Java se1.6 对synchronized进行了各种优化后,有些情况下它就并不那么重了。 synchronized实现同步的基础:每个对象都可以作为锁,具体分为三种情况: 对于普通同步方法,锁的是自己实力对象 对于静态同步方法,锁的是当前类的Class对象 对于同步方法快,锁的是synchronized括号里配置的对象 JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但是两者实现细节不同: 代码块同步是使用monitorenter和monitorexit指令实现的。 同步方式使用的另一种方法实现。 monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证每个monitorenter和monitorexit成对出现。 任何一个对象都有一个monitor与之关联, 当且一个monitor被持有后,它将处于锁定状态。 线程执行到monitorenter指令时,将尝试获得对象所对应的monitor的所有权,即尝试获得对象的锁。 2、synchronized用的锁是存在Java对象头里的。如果对象是数组类型的话,则JVM用3个字节存储对象头,如果对象是非数组类型的话,则用2个字节存储对象头。 3、锁升级与对比 Java

2020 Java面试题最新(五锁机制)

无人久伴 提交于 2020-02-10 17:44:28
锁的原因都是由并发问题发生的,在此我只是写一些面试中可能会问到的问题以及问题的答案,并不是给大家深入的讲解锁机制 一般面试官问都是从一个点引入一个点的问问题,所以我就先从线程问题引入到锁问题 1.说说线程安全问题 线程安全是多线程领域的问题,线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题 在 Java 多线程编程当中,提供了多种实现 Java 线程安全的方式: 最简单的方式,使用 Synchronization 关键字 使用 java.util.concurrent.atomic 包中的原子类,例如 AtomicInteger 使用 java.util.concurrent.locks 包中的锁 使用线程安全的集合 ConcurrentHashMap 使用 volatile 关键字,保证变量可见性(直接从内存读,而不是从线程 cache 读) 2.volatile 实现原理 在 JVM 底层 volatile 是采用“内存屏障”来实现的 缓存一致性协议(MESI协议)它确保每个缓存中使用的共享变量的副本是一致的。其核心思想如下:当某个 CPU 在写数据时,如果发现操作的变量是共享变量,则会通知其他 CPU 告知该变量的缓存行是无效的,因此其他 CPU 在读取该变量时,发现其无效会重新从主存中加载数据 3.synchronize 实现原理

并发编程之第三篇(synchronized)

与世无争的帅哥 提交于 2020-02-10 12:02:55
并发编程之第三篇(synchronized) 3. 自旋优化 4. 偏向锁 撤销-其它线程使用对象 撤销-调用wait/notify 批量重偏向 批量撤销 5. 锁消除 4.7 wait/notify API介绍 4.8 wait notify的正确姿势 同步模式之保护性暂停 异步模式之生产者/消费者 4.9 Park & Unpark 原理之park & unpark 4.10 重新理解线程状态转换 3. 自旋优化 重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这时候持锁线程已经退出了同步块,释放了锁),这时当前线程就可以避免阻塞。 自旋重试成功的情况 自旋重试失败的情况 在Java6之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。 自旋会占用CPU时间,单核CPU自旋就是浪费,多核CPU自旋才能发挥优势。 Java7之后不能控制是否开启自旋功能 4. 偏向锁 轻量级锁在没有竞争时(就自己这个线程),每次重入任然需要执行CAS操作。 Java6中引入了偏向锁来做进一步优化 :只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS。以后只要不发生竞争,这个对象就归该线程所有 例如 : 偏向状态

CAS解析

喜夏-厌秋 提交于 2020-02-06 10:51:47
CAS:compare and swap,也有的叫做 compare and set;意思都差不多,翻译过来就是比较并交换或者比较并设值。 CAS包含三个值,内存地址(V),预期值(A),新值(B)。先比较内存地址的值和预期的值是否相等,如果相等,就将新值赋在内存地址上,否则,不做任何处理。这种是乐观锁的思想。 源码解析 CAS操作在JUC中大量用到,在解析AQS那章中,我们也有提到。再回头看一下AQS中CAS的操作 protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } 这里是对AQS中state变量进行的CAS操作,要知道,很多同步类都是通过这个变量来实现线程安全的,所以在AQS中,首先要保证对state的赋值是线程安全的。 在java中,不论什么操作,只要他还是在Java api级别,就不能保证他一定是线程安全的,除非这个操作调用系统资源来支持。这里保证state线程安全是通过unsafe中的compareAndSwapInt方法来实现的,里面的参数stateOffset就是内存地址(V),expect是预期值(A),新值(B)。在unsafe中

STT-MRAM存在的两个弊端

可紊 提交于 2020-02-05 14:43:06
随着自旋转移矩效应的发现以及材料和结构的优化,基于自旋转移矩效应的 STT-MRAM 器件应运而生。自从自旋转移矩效应被证实以来,一方面研究人员通过大量的努力尝试降低磁化反转的临界电流,增加热稳定性;另一方面Sony、Hitachi、Renesas、Crocus、Toshiba、Samsung、Hynix、IBM等多家公司也在积极研发STT-MRAM。 早期的磁隧道结采用面内磁各向异性(In-Plane Magnetic Anisotropy)。它存在如下两个弊端: 1)随着工艺减小,热稳定性恶化。采用面内磁各向异性磁隧道结的存储寿命取决于热稳定性势垒和磁各向异性场,面内磁各向异性的来源是薄膜平面较大的长宽比。 随着工艺尺寸的微缩(<50nm),这种薄膜的边际效应加剧,会产生显著的磁涡旋态,难以保持较高的热稳定性势垒,甚至稳定的磁化也无法存在,这将限制MRAM的存储密度; 其次面内磁各向异性的磁隧道结降低了自旋转移矩的翻转效率 因此,对于相同的热稳定性势垒,垂直磁各向异性能够使磁隧道结的临界翻转电流比面内磁各向异性的更低,相应地,自旋转移矩的翻转效率更高。鉴于上述优势,研究人员也一直致力于采用垂直磁各向异性的磁隧道结结构建高密度、低功耗的pSTT-MRAM。 图1(a)垂直磁各向异性的磁隧道结;(b)沿面内和垂直方向的磁化曲线,证明易磁化轴沿垂直方向。 目前最新的低功耗

谈谈线程安全与锁优化

佐手、 提交于 2020-02-04 02:46:02
写在前面 本文是作为阅读《深入理解Java虚拟机》第13章线程安全与锁优化的读书笔记; 线程安全是以多个线程之间存在共享对象为前提的。它并不是一个非黑即白的问题。Brian Goetz 曾就线程安全的“安全程度” 按以下由强至弱做了划分: 不可变;这类对象不需要进行任何线程安全的保障措施,只要这个对象被构建出来,其外部的可见状态永远也不会改变。如果共享数据是一个基本数据类型,那么只要在定义时使用 final 关键字修饰它,就可以保证它是不可变的。如果共享数据是一个对象类型,那就需要保证对象的行为不会对其状态产生任何影响才行,像 String 类的对象。 绝对线程安全;这类的划分的定义和不可变很像,但不可变更加的纯粹,简单。如果一个对象要是绝对线程安全的,那么需要保证多个线程中,对该对象的各种行为调用组合,都会得到想要的结果。举个例子来说, Vector 是线程安全的,但并不是绝对线程安全,比如,在一个线程对一定容量大小的 Vector 进行 remove 操作,另一线程进行 get 操作,最终,你会得到一个数组越界异常,这并不是我们想要的结果。其实,绝对线程安全是一种很苛刻的条件,所以,Java 中所讲的线程安全,通常指的是下面的相对线程安全。 相对线程安全;针对单个对象的单独操作是线程安全的。像上面 Vector 的 get 、remove 等操作。 线程兼容

【架构师技巧分享】程序员面试美团:面试官突然问Java “锁”你应该怎么回答?

天涯浪子 提交于 2020-02-02 18:02:15
【架构师技巧分享】程序员面试美团:面试官突然问Java “锁”你应该怎么回答? Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。 Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录: 1.乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的实际应用。 先说概念。对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。 乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法

自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析

蹲街弑〆低调 提交于 2020-01-31 03:56:30
转自:http://blog.csdn.net/wh_19910525/article/details/11536279 自旋锁的初衷:在短期间内进行 轻量级的锁定 。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋( 特别浪费处理器时间 ),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。 单处理器的自旋锁: 首先,自旋锁的目的如果在系统不支持内核抢占时,自旋锁的实现也是空的,因为单核只有一个线程在执行,不会有内核抢占,从而资源也不会被其他线程访问到。 其次,支持内核抢占,由于自旋锁是禁止抢占内核的,所以不会有其他的进程因为等待锁而自旋. 最后,只有在多cpu下,其他的cpu因为等待该cpu释放锁,而处于自旋状态,不停轮询锁的状态。所以这样的话,如果一旦自旋锁内代码执行时间较长,等待该锁的cpu会耗费大量资源,也是不同于信号量和互斥锁的地方。 简单来说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。 自旋锁内睡眠禁止睡眠问题: 如果自旋锁锁住以后进入睡眠,而此时又不能进行处理器抢占(锁住会disable prempt),其他进程无法获得cpu,这样也不能唤醒睡眠的自旋锁,因此不相应任何操作。 自旋锁为什么广泛用于内核: 自旋锁是一种轻量级的互斥锁,可以更高效的对互斥资源进行保护

java 锁机制

喜欢而已 提交于 2020-01-30 21:21:12
公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁(实现秒杀的一种解决方案) (select * from product p where p.type=’xxxxx’ for update) 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计, 公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁是指多个线程获取锁的顺序并不按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。 对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。 对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。 AQS 的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。 CLH (Craig,Landin,and Hagersten)队列是一个虚拟的双向队列