volatile

Synchronized、Threadlocal、Volatile

感情迁移 提交于 2020-01-09 14:38:28
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

C中的volatile用法

冷暖自知 提交于 2020-01-09 08:34:35
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2) 一个中断服务子程序中会访问到的非自动变量(Non

What is the point of making the singleton instance volatile while using double lock? [duplicate]

寵の児 提交于 2020-01-09 06:01:08
问题 This question already has answers here : Why is volatile used in double checked locking (6 answers) Closed 2 years ago . private volatile static Singleton uniqueInstance In a singleton when using double lock method for synchronization why is the single instance declared as volatile ? Can I achieve the same functionality without declaring it as volatile ? 回答1: Without volatile the code doesn't work correctly with multiple threads. From Wikipedia's Double-checked locking: As of J2SE 5.0, this

C中的volatile用法

喜夏-厌秋 提交于 2020-01-09 04:07:21
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2) 一个中断服务子程序中会访问到的非自动变量(Non

Are volatile variable 'reads' as fast as normal reads?

故事扮演 提交于 2020-01-09 02:15:13
问题 I know that writing to a volatile variable flushes it from the memory of all the cpus, however I want to know if reads to a volatile variable are as fast as normal reads? Can volatile variables ever be placed in the cpu cache or is it always fetched from the main memory? 回答1: You should really check out this article: http://brooker.co.za/blog/2012/09/10/volatile.html. The blog article argues volatile reads can be a lot slower (also for x86) than non-volatile reads on x86. Test 1 is a parallel

java 用volatile和不用volatile的区别

守給你的承諾、 提交于 2020-01-09 02:05:00
在当前的 Java 内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。 要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。 Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 用volatile和不用volatile的区别,运行一下,就知道了。 不用volatile: package com.keyword; public class TestWithoutVolatile { private static boolean bChanged; public static void main(String[] args) throws InterruptedException { new Thread() { @Override public void run() { for (;;) { if

C中的volatile用法

女生的网名这么多〃 提交于 2020-01-09 00:29:50
.volatile的本质: 1> 编译器的优化 在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。 当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。 当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。 2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。 volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作

[转帖]synchronized、lock和cas理解

徘徊边缘 提交于 2020-01-08 23:59:14
synchronized、lock和cas理解 https://blog.csdn.net/qq_41908272/article/details/94736856 这是小编我在看完ReentrantLock类之后对这几种可以实现锁的方式的理解,如果有什么理解的不对的,大家可以一起交流,共同进步。 synchronized synchronized这个关键子是java语言中可以用于实现锁的一种方式。这个关键字我们一般称为同步。这种加锁的方式也是我们平常经常用到的,就比如说小编前段时间碰到的一个问题,用户领取优惠券,这时发现一个用户在领取优惠券时都会发生多领的情况,不用考虑,直接加锁,这是可以不费吹灰之力就可以解决问题的方式。但是加在哪里,怎么加这是很有可能会影响到系统的运行速度。现在先来看下synchronized可以加在哪几个地方,并说一下加在这些地方会对什么东西上锁。 //1⃣️ synchronized (this){ } //2⃣️ public synchronized void tset(){ } //3⃣️ synchronized (类名.class){ } 在上面的代码块中,这是synchronized可以加在这几个地方,加在不同的地方锁住的对象也是不同的,就比如说1和3,就是锁住当前进入这个方法的实例,即是锁住对象,2就是锁住这个方法

如何停止JAVA线程

只谈情不闲聊 提交于 2020-01-08 23:35:46
本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! http://blog.csdn.net/anhuidelinger/article/details/11746365 终止线程的三种方法 有三种方法可以使终止线程。 1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。 2. 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。 3. 使用interrupt方法中断线程。 1. 使用退出标志终止线程 当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。 在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使 while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环 是否退出。下面给出了一个利用退出标志终止线程的例子。 package chapter2; public class ThreadFlag extends Thread { public

Java 并发进阶常见面试题总结

孤街浪徒 提交于 2020-01-08 23:06:27
Java 并发进阶常见面试题总结 1. synchronized 关键字 1.1. 说一说自己对于 synchronized 关键字的了解 synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。 另外,在 Java 早期版本中,synchronized属于重量级锁,效率低下,因为监视器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,这也是为什么早期的 synchronized 效率低的原因。庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。JDK1.6对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。 1.2. 说说自己是怎么使用 synchronized 关键字,在项目中用到了吗 synchronized关键字最主要的三种使用方式: 修饰实例方法: