synchronized

volatile和synchronized的区别

和自甴很熟 提交于 2020-01-05 03:41:14
volatile和synchronized特点 首先需要理解线程安全的两个方面: 执行控制 和 内存可见 。 执行控制 的目的是控制代码执行(顺序)及是否可以并发执行。 内存可见 控制的是线程执行结果在内存中对其它线程的可见性。根据 Java内存模型 的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存。 synchronized 关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被 synchronized 关键字保护的代码块无法被其它线程访问,也就无法并发执行。更重要的是, synchronized 还会创建一个 内存屏障 ,内存屏障指令保证了所有CPU操作结果都会直接刷到主存中,从而保证了操作的内存可见性,同时也使得先获得这个锁的线程的所有操作,都 happens-before 于随后获得这个锁的线程的操作。 volatile 关键字解决的是内存可见性的问题,会使得所有对 volatile 变量的读写都会直接刷到主存,即保证了变量的可见性。这样就能满足一些对变量可见性有要求而对读取顺序没有要求的需求。 使用 volatile 关键字仅能实现对原始变量(如boolen、 short 、int 、long等)操作的原子性,但需要特别注意, volatile 不能保证复合操作的原子性,即使只是

Java多线程之synchronized和volatile

爱⌒轻易说出口 提交于 2020-01-05 03:40:18
概述 用Java来开发多线程程序变得越来越常见,虽然Java提供了并发包来简化多线程程序的编写,但是我们有必要深入研究一下,才能更好的掌握这块知识。 本文主要对Java提供的底层原语synchronized和volatile进行分析,看看他们究竟干了什么,以及怎么样才能合理的使用它们。 运算速度与IO速度的问题 现代计算机模型,待计算的数据主要存储在内存中,CPU想要对数据进行计算,就必须要经过下面的流程:从内存读取数据-->CPU计算-->把计算结果写回内存。但是,不得不承认一个事实,就是CPU与内存之间的IO速度,要比CPU的运算速度慢很多,所以这样就不能充分发挥CPU的计算能力。 为了解决这个问题,引入了高速缓存的概念,它一般位于内存与CPU之间,与CPU之间有较高的IO速度。高速缓存存放常用的数据,这样就可以大幅度提高CPU的利用率。 由缓存命中问题引出的指令重排序 上面提到了高速缓存之间的概念。既然提到高速缓存,那么就要谈到缓存命中的问题,如果缓存命中率很高,那么整体性能就会提升。所以,试想一下,有下面几行代码: int a = 0; a = a + 10; int b = 0; b = b + 5; a = a * 2; 通常我们会认为,执行完第2条代码后,a被写入到高速缓存,然后执行对b的操作,最后再从高速缓存中读取出a,再对a做乘法计算。 但是

C#中volatile的用法

拟墨画扇 提交于 2020-01-05 03:39:40
注:本文为个人学习摘录,原文地址:http://www.cnblogs.com/gjhjoy/p/3556709.html 恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码: int i1 ; int geti1 () { return i1 ; } volatile int i2 ; int geti2 () { return i2 ; } int i3 ; synchronized int geti3 () { return i3 ; }   geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改 变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程 可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值 是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。    而geti2()得到的是“主

Synchronized、Threadlocal、Volatile

孤人 提交于 2020-01-05 03:21:36
synchronized: synchronized叫做同步锁,操作起来方便,只需要在一个方法或把需要同步的代码块包装在它内部,那么这段代码就是同步的了,所有线程对这块区域的代码访问必须先持有锁才能进入,否则则拦截在外面等待正在持有锁的线程处理完毕再获取锁进入正因为它基于这种阻塞的策略,所以它的性能不太好,但是由于操作上的优势, 只需要简单的声明一下即可,而且被它声明的代码块也是具有操作的原子性。 threadlocal (本地单机) 用来提供线程内的局部变量,这样每个线程都自己管理自己的局部变量,别的线程操作的数据不会对我产生影响,互不影响 就是把变量分成很多个拷贝,每个线程拥有一个。这里没有所谓的最后的结果,每个线程单独操作自己的变量,和其他的变量没关系,互不干扰 ThreadLocalMap类的定义是在ThreadLocal类中,真正的引用却是在Thread类中。同时,ThreadLocalMap中用于存储数据的entry定义,它是一个Map,他的key是ThreadLocal实例对象。 1、JVM利用设置ThreadLocalMap的Key为弱引用,来避免内存泄露。 2、JVM利用调用remove、get、set方法的时候,回收弱引用 3、当ThreadLocal存储很多Key为null的Entry的时候,而不再去调用remove、get、set方法,那么将导致内存泄漏 4

java Map集合对比分析

左心房为你撑大大i 提交于 2020-01-05 02:24:34
1、 Map:Map 是所有 map 集合的顶级父接口,用于 key/value 形式的键值对,其中每一个 key 都映射到一个值, key 不能重复。 2、 TreeMap: 该 map 将存储的键值对进行默认排序,并且还能够指定排序的比较器,是线程不安全的。 TreeMap 不允许键值为 null 。 // 指定比较器进行排序 Map map = new TreeMap(new Comparator(){ Public int compare(obj1, obj2){...} }); 3、 HashMap: 这也是我们平时开发中最常用的 map ,底层实现为数组+链表,它根据键 key 的 HashCode 值存储数据,可以使用 get(key) 来获取键对应的值,是线程不安全的。 HashMap 允许存在一条键为 null 的记录。在数据量小的时候, HashMap 是以链表的模式存储数据;当数据量变大后,为了进行快速查找,会将这个链表变为红黑树来进行保存,使用 key 的哈希值来进行查找。 4、 Hashtable: 与 HashMap 类似,不同的是, Hashtable 是线程安全的,在进行插入是会比 HashMap 慢,并且 key 和 value 的值均不允许为 null 。对个线程同时访问 Hashtable 对象时,第一个线程获取锁后,会引发其他线程进行等待

并发编程之多线程线程安全(上)

拜拜、爱过 提交于 2020-01-04 06:14:09
1、为什么有线程安全问题? 当多个线程共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。 案例:现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。 代码: public class NewThread1 implements Runnable{ private int trainCount = 100; @Override public void run() { while (trainCount>0){ try { Thread.sleep(100); }catch (Exception e){ } save(); } } private void save() { if (trainCount > 0) { System.out.println(Thread.currentThread().getName() + ",出售第" + (100 - trainCount + 1) + "张票"); trainCount--; } } public static void main(String[] args){ NewThread1 newThread1 = new NewThread1(); Thread thread1 = new Thread(newThread1,"①");

How to avoid synchronization on a non-final field?

大兔子大兔子 提交于 2020-01-04 05:34:07
问题 If we have 2 classes that operate on the same object under different threads and we want to avoid race conditions, we'll have to use synchronized blocks with the same monitor like in the example below: class A { private DataObject mData; // will be used as monitor // thread 3 public setObject(DataObject object) { mData = object; } // thread 1 void operateOnData() { synchronized(mData) { mData.doSomething(); ..... mData.doSomethingElse(); } } } class B { private DataObject mData; // will be

volatile、synchronized、lock有什么区别,以及在哪些场景下使用哪种方式?

醉酒当歌 提交于 2020-01-04 05:15:33
[转]JVM锁机制volatile/synchronized/lock 1.volatile实现原理 (1) 聊聊并发(一)——深入分析Volatile的实现原理 --硬件级别锁实现,Lock前缀指令会引起处理器缓存(CPU高级缓存L1/L2/L3)回写到内存。一个处理器的缓存回写到内存会导致其他处理器的缓存无效。 2.JVM锁机制--synchronized (1) 深入JVM锁机制1-synchronized --自旋锁、偏向锁 --synchronized的底层实现主要依靠Lock-Free的队列,基本思路是自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。 (2) 聊聊并发(二)——Java SE1.6中的Synchronized -- 偏向锁—>轻量锁—>重量锁 比较 偏向锁 Hotspot的作者经过以往的研究发现大多数情况下锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要花费CAS操作来加锁和解锁,而只需简单的 测试 一下对象头的Mark Word里是否存储着指向当前线程的偏向锁,如果测试成功,表示线程已经获得了锁,如果测试失败,则需要再测试下Mark Word中偏向锁的标识是否设置成1

并发Bug之源有三,请睁大眼睛看清它们

会有一股神秘感。 提交于 2020-01-04 05:13:31
写在前面 生活中你一定听说过——能者多劳 作为 Java 程序员,你一定听过——这个功能请求慢,能加一层缓存或优化一下 SQL 吗? 看过中国古代神话故事的也一定听过——天上一天,地上一年 一切设计来源于生活,上一章 学并发编程,透彻理解这三个核心是关键 中有讲过,作为"资本家",你要尽可能的榨取 CPU,内存与 IO 的剩余价值,但三者完成任务的速度相差很大,CPU > 内存 > IO分,CPU 是天,那内存就是地,内存是天,那 IO 就是地,那怎样平衡三者,提升整体速度呢? CPU 增加缓存,还不止一层缓存,平衡内存的慢 CPU 能者多劳,通过分时复用,平衡 IO 的速度差异 优化编译指令 上面的方式貌似解决了木桶短板问题,但同时这种解决方案也伴随着产生新的 可见性,原子性,和有序性 的问题,且看 三大问题 可见性 一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性 谈到可见性,要先引出 JMM (Java Memory Model) 概念, 即 Java 内存模型,Java 内存模型规定,将所有的变量都存放在 主内存 中,当线程使用变量时,会把主内存里面的变量 复制 到自己的工作空间或者叫作 私有内存 ,线程读写变量时操作的是自己工作内存中的变量。 用 Git 的工作流程理解上面的描述就很简单了, Git 远程仓库就是主内存,Git 本地仓库就是自己的工作内存

java保证多线程的执行顺序

空扰寡人 提交于 2020-01-04 04:53:43
1. java多线程环境中,如何保证多个线程按指定的顺序执行呢? 1.1 通过thread的join方法保证多线程的顺序执行, wait是让主线程等待 比如一个main方法里面先后运行thread1,,thread2,thread3,那么thread1.start()之后,运行thread1.join(),这是会让主线程mian等待新的线程thread1执行完了,再执行主线程mian下面的代码,thread1.join()是然主线程main wait。 package com.java.yj; /** * Created by yejian on 2018/7/9. */ public class MultiThread { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new Thread1()); thread1.start(); thread1.join(); Thread thread2 = new Thread(new Thread2()); thread2.start(); thread2.join(); Thread thread3 = new Thread(new Thread3()); thread3.start();