volatile和 锁的区别】的更多相关文章

Volatile: 当把变量声明为volatile类型后,编译器和运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其它内存操作一起重排序.volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型变量时总会返回最新的值. 也就是说volatile类型的变量保证了可见性 但是不能保证原子性 在进行自增等非原子性操作的时候依然会出现并发问题. Volatile和锁: 当多个线程同时请求锁的时候,一些线程将被挂起并且等待其他线程执行完它们的时间片后才…
volatile和synchronized特点 首先需要理解线程安全的两个方面:执行控制和内存可见. 执行控制的目的是控制代码执行(顺序)及是否可以并发执行. 内存可见控制的是线程执行结果在内存中对其它线程的可见性.根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存. synchronized关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被synchronized关键字保护的代码块…
java线程的内存模型 java的线程内存模型中定义了每个线程都有一份自己的共享变量副本(本地内存),里面存放自己私有的数据,其他线程不能直接访问,而一些共享变量则存在主内存中,供所有线程访问. 上图中,如果线程A和线程B要进行通信,就要经过主内存,比如线程B要获取线程A修改后的共享变量的值,要经过下面两步: (1).线程A修改自己的共享变量副本,并刷新到了主内存中.      (2).线程B读取主内存中被A更新过的共享变量的值,同步到自己的共享变量副本中. 总结:在java内存模型中,共享变量…
一.指令重排问题 你写的代码有可能,根本没有按照你期望的顺序执行,因为编译器和 CPU 会尝试指令重排来让代码运行更高效,这就是指令重排. 1.1 虚拟机层面 我们都知道CPU执行指令的时候,访问内存的速度远慢于 CPU 速度. 为了尽可能减少内存操作带来的 CPU 空置的影响,虚拟机会按照自己的一些规则将程序编写顺序打乱:即写在后面的代码在时间顺序上可能会先执行,而写在前面的代码会后执行. 当然这样的前提是不会产生错误.不管谁先开始,总之后面的代码在一些情况下存在先结束的可能. 1.2 硬件层…
Volatile 英文翻译:易变的.可变的.不稳定的. 一.volatile 定义及用法 多个线程的工作内存彼此独立,互不可见,线程启动的时候,虚拟机为每个内存分配一块工作内存,不仅包含了线程内部定义的局部变量,也包含了线程所需要使用的共享变量的副本,是为了提高效率. 在之前的示例中,线程不安全的问题,我们使用线程同步,也就是通过 synchronized 关键字,对操作的对象加锁,屏蔽了其他线程对这块代码的访问,从而保证安全. 这里的 volatile 尝试从另一个角度解决这个问题,那就是保证…
在ReentrantLock中包含了公平锁和非公平锁两种锁,通过查看源码可以看到这两种锁都是继承自Sync,而Sync又继承自AbstractQueuedSynchronizer,而AbstractQueuedSynchronizer又继承自AbstractOwnableSynchronizer,下面是类的继承关系图: 其中AbstractOwnableSynchronizer是提供了设置占用当前锁的线程信息的方法,主要的锁的实现还是在AbstractQueuedSynchronizer中实现的…
在ReentrantLock中包含了公平锁和非公平锁两种锁,通过查看源码可以看到这两种锁都是继承自Sync,而Sync又继承自AbstractQueuedSynchronizer,而AbstractQueuedSynchronizer又继承自AbstractOwnableSynchronizer,下面是类的继承关系图:  其中AbstractOwnableSynchronizer是提供了设置占用当前锁的线程信息的方法,主要的锁的实现还是在AbstractQueuedSynchronizer中实现…
java 对象锁和类锁的区别   转自; ) ); ; ) ); 上述的代码,第一个方法时用了同步代码块的方式进行同步,传入的对象实例是this,表明是当前对象,当然,如果需要同步其他对象实例,也不可传入其他对象的实例:第二个方法是修饰方法的方式进行同步.因为第一个同步代码块传入的this,所以两个同步代码所需要获得的对象锁都是同一个对象锁,下面main方法时分别开启两个线程,分别调用test1和test2方法,那么两个线程都需要获得该对象锁,另一个线程必须等待.上面也给出了运行的结果可以看到:…
synchronized和锁(ReentrantLock) 区别 java的两种同步方式, Synchronized与ReentrantLock的区别 并发(一):理解可重入锁 可重入锁和不可重入锁 ReentrantLock & synchronize Java并发之ReentrantLock详解 package mianshi.test; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Reent…
Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchronized(下文简称:sync)和lock(下文就用ReentrantLock来代之lock)的区别. 本文主要内容:将通过七个方面详细介绍sync和lock的区别.通过生活case中的X二代和普通人比较大家更容易理解这两者之间的区别 Java中隐式锁:synchronized:显式锁:lock…
volatile和synchronized的区别 volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取: synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住. volatile仅能使用在变量级别:synchronized则可以使用在变量.方法.和类级别的 volatile仅能实现变量的修改可见性,不能保证原子性:而synchronized则可以保证变量的修改可见性和原子性 volatile不会造成线程的阻塞:sync…
volatile 它所修饰的变量不保留拷贝,直接访问主内存中的.   在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己的memory中保持要访问的变量的副本.这样就会出现同一个变 量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况. 一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中…
volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符.所以我们使用这两种关键字来指定三种简单的存取变量的方式. int i1;                       int geti1() {return i1;} volatile int i2;                       int geti2() {return i2;} int i3;          synchronized int geti3() {return i3;} geti1…
在网络上看了很多关于他们两个的区别与联系,今天用自己的话表述一下: synchronized 容易理解,给一个方法或者代码的一个区块加锁,那么需要注意的是,加锁的标志位默认是this对象,当然聪明的你可能想我能不能不用this对象而使用其他的哪?答案是肯定的 volatile 说volatile就不得不说JAVA的内存模型,java的每一个线程都有自己的指定的内存区域,而且又有共同的主内存区域,当操作计算的时候,会从主内存区域将变量拷贝到自己的内存区域,再计算,计算之后再写回去,那么问题就来了,…
      一.原子性 原子性操作指相应的操作是单一不可分割的操作.例如,对int变量count执行count++d操作就不是原子性操作.因为count++实际上可以分解为3个操作:(1)读取变量count的当前值:(2)拿count的当前值和1做加法运算:(3)将加完后的值赋给count变量. 在多线程环境中,非原子操作可能会受其他线程的干扰.比如,上述例子如果没有对相应的代码进行同步(Synchronization)处理,则可能出现在执行第2个操作的时候,count变量的值已经被其他线程修改…
1.锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility). 互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据. 可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享         变量可能是修改前的值或不一致的值,这将引发许多严重问题.(竞态条件) 2.在Java中…
线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只能被一个线程持有,可以重入(表示一个处于synchronized代码中的线程可以进入另外一个使用synchronized的代码快,比如:方法A和方法B同时使用synchronized修饰,在方法A中调用了方法B,调用某个线程调用方法A的时候不会造成死锁,因为synchronized是可重入的锁,线程…
volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞. synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行.多个线程争抢synchronized锁对象时,会出现阻塞. volatile本质是在告诉…
Synchronized和Volatile四个不同点: 1.粒度不同,前者锁对象和类 ,后者针对变量2.syn阻塞,volatile线程不阻塞3.syn保证三大特性,volatile不保证原子性4.syn编译器优化,volatile不优化   要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件: 1.对变量的写操作不依赖于当前值. 2.该变量没有包含在具有其他变量的不变式中.…
https://www.cnblogs.com/RunForLove/p/5543545.html 先来看一段代码,实现如下打印效果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 11 12 F 13 14 G 15 16 H 17 18 I 19 20 J 21 22 K 23 24 L 25 26 M 27 28 N 29 30 O 31 32 P 33 34 Q 35 36 R 37 38 S 39 40 T 41 42 U 43 44 V 45 46 W 47 48 X…
一.volatile 的内存语义 1. volatile 的特性 volatile变量自身具有以下特性: 可见性 :对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入. 原子性 :对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性. 2. volatile 写-读建立的happens-before关系 从JSR-133开始(即从JDK5开始),volatile变量的写-读可以实现线程之间的通信. 从内存语…
双重锁实现单例时遭到质疑,既是:双重锁也无法保证单例模式! 原因是:指令会重排序,普通的变量仅仅会保证该方法在执行时,所有依赖的赋值结果是正确的,但不会保证执行顺序! 为什么会重排序:指令重排序是指cpu采用了允许将多条指令不按照程序的顺序分开发送各相应电路单元处理,cpu不会任意排序(深入java虚拟机第12章),但需要重排序提高性能. 怎么解决,标题也写明白了. 使用volatile关键字! 为什么使用volatile关键字可以实现:此关键字会禁止指令重排序,即:增加了内存屏障! 如果是一个…
仅靠Volatile不能保证线程的安全性(原子性) 1.Volatile轻量级的,只能修饰变量.synchronize重量级的,还可以修饰方法 2.Volatile只保证数据的可见性,不能用来同步,因为多线程访问Volatile变量不会阻塞 3.synchronize不仅保证可见性,而且保证原子性,因为自由获得了锁的线程才能到达临界区,从而保证了临界区中的所有语句被执行,多个线程抢夺synchronize锁的时候,会出现阻塞. 注意:Volatile不具有原子性,不保证线程的安全.…
让编译器不要将变量缓存到寄存器,而是每次去访问主板上的内存 可见性 对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入 原子性 对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性(volatile的使用不要依赖自身) 不被编译器优化 XBYTE[2]=0x55; XBYTE[2]=0x56; 使用地方 中断服务程序中修改的供其它程序检测的变量 多任务环境下各任务间共享的标志 存储器映射的硬件寄存器 性能比…
JMM (Java内存模型) Java线程的实现 实现线程主要有三种方式,Java线程从JDK1.3后采用第一种方式实现: 使用内核线程实现(1:1实现) 使用用户线程实现(1:N实现) 使用用户线程加轻量级进程混合实现(N:M实现) KTL: 内核线程 LWP:轻量级进程 UT:用户线程 线程之间通信机制 Java并发采用的是共享内存模型 共享内存 消息传递 重排序 包括: 编译器优化的重排序. 指令级并行的重排序.如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序. 内存系统的重…
目录 锁类型 可中断锁 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 Synchronized与Static Synchronized 举例 Lock 定义 四种获取Lock的方法区别 lock() tryLock() tryLock(long time, TimeUnit unit) lockInterruptibly() synchronized与Lock的区别 锁类型 可中断锁 在等待获取锁过程中可中断 Lock就是…
13.显示锁 在Java5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile.Java5.0增加了一种新的机制:ReentrantLock.与之前提到过的机制相反,RenntrantLock并不是一种替代内置加锁的方法,而是当内置锁机制不适用时,作为一种可选择的高级功能. 13.1 ReentrantLock Lock接口提供了一组抽象的加锁操作,与内置加锁操作不同的是,Lock提供了一种无条件的.可轮训的.定时的以及可中断锁操作,所有加锁和解锁的方法…
悲观锁 它指的是对数据被外界修改持保守态度.假定任何时刻存取数据时,都可能有另一个客户也正在存取同一笔数据,为了保持数据被操作的一致性,于是对数据采取了数据库层次的锁定状态,依靠数据库提供的锁机制来实现. 基于jdbc实现的数据库加锁如下: select * from account where name="Erica" for update 在更新的过程中,数据库处于加锁状态,任何其他的针对本条数据的操作都将被延迟.本次事务提交后解锁. 而hibernate悲观锁的具体实现如下: S…
NOLOCK(不加锁)    此选项被选中时,SQL  Server  在读取或修改数据时不加任何锁.  在这种情况下,用户有可能读取到未完成事务(Uncommited  Transaction)或回滚(Roll  Back)中的数据,  即所谓的“脏数据”.            HOLDLOCK(保持锁)    此选项被选中时,SQL  Server  会将此共享锁保持至整个事务结束,而不会在途中释放.    例如,“ SELECT * FROM my_table HOLDLOCK”就要求在…
定义: 悲观锁(Pessimistic Lock): 每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁.由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待. 乐观锁(Optimistic Lock): 每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过.如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程…