volatile

Java多线程面试问题和答案

北战南征 提交于 2020-01-13 16:38:46
1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。Java在语言层面对多线程提供了卓越的支 持,它也是一个很好的卖点。 2) 线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。 3) 如何在Java中实现线程? 在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承 java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。 4) 用Runnable还是Thread? 这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程,问题是,那个方法更好呢?什么情况下使 用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类

多线程实现同步

血红的双手。 提交于 2020-01-13 15:38:57
多线程的三大特性: 原子性:即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行 可见性:当多个线程访问一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值 有序性:程序执行的顺序按照代码的先后顺序执行 多线程实现同步: 线程安全:当多个线程同时对共享的一个全局变量或者静态变量做写操作时,可能会发生数据冲突问题,也就是线程安全问题,但是做读操作是不会发生数据冲突问题 线程安全解决方法:使用多线程之间同步synchronized或者使用lock(锁)          同一时间只让当前一个线程进行对数据进行执行操作,当前线程执行完成后释放锁,才能让其他线程进行操作执行,避免了同时对数据的操作,这样的华就可以解决线程的不安全问题,也就是实现了数据的同步 synchronized两种用法: 第一种:将可能会发生线程安全问题的代码,给包括起来,称为同步代码块 第二种:在方法上修饰synchronized,称为同步函数 静态同步函数使用的锁是该函数所属字节码文件对象,可以使用getClass()方法获取,也可以用当前类名.class表示 同步的前提: 1.要有两个或者两个以上的线程,否则没有意义 2.多线程使用同一个锁 必须保证同步中只有一个线程运行 什么是Volatile? volatile是java提供的一种同步手段,它是轻量级的同步

java 中的volatile

ⅰ亾dé卋堺 提交于 2020-01-13 13:45:44
本博客摘录自 http://www.infoq.com/cn/articles/java-memory-model-4/ 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别。理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这些单个读/写操作做了同步。下面我们通过具体的示例来说明,请看下面的示例代码: 1 class VolatileFeaturesExample { 2 volatile long vl = 0L; //使用volatile声明64位的long型变量 3 4 public void set(long l) { 5 vl = l; //单个volatile变量的写 6 } 7 8 public void getAndIncrement () { 9 vl++; //复合(多个)volatile变量的读/写 10 } 11 12 13 public long get() { 14 return vl; //单个volatile变量的读 15 } 16 } 假设有多个线程分别调用上面程序的三个方法,这个程序在语意上和下面程序等价: 1 class VolatileFeaturesExample { 2 long vl = 0L; // 64位的long型普通变量 3 4 public

枚举java语言中的修饰符组合

对着背影说爱祢 提交于 2020-01-13 11:56:01
package model; /*22:37 2019/7/20*/ /* top class的修饰符组合 abstract final public 2 * 2 * 2 warning: abstract final 冲突 最终,共有2*(2*2-1)=6种修饰符组合用于top class */ /* public abstract class PublicAbstractClass{} public final class PublicFinalClass{} abstract class AbstractClass{} final class FinalClass{} public class PublicClass{} class Class{} 关于constructor的修饰符组合 abstract [DEFAULT] protected public 关于field的修饰符组合 4 * 2 * 2 * 2 * 2 权限 静态的 瞬态的 同步的 private 缺省 缺省 缺省 缺省 缺省 (not final) (not static) (not transient) (not volatile) protected public final static transient volatile warning: volatile final 冲突 最终,共有4*2*2

volatile的作用

淺唱寂寞╮ 提交于 2020-01-13 09:48:31
volatile的作用 标签: 生活 2010-09-17 10:29 星期五   volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。   使用该关键字的例子如下:   int volatile nVint;   >>>>当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。   例如:   volatile int i=10;   int a = i;   ...   //其他代码,并未明确告诉编译器,对i进行过操作   int b = i;   >>>>volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。   >>>>注意,在vc6中,一般调试模式没有进行代码优化

搞懂线程、多线程和线程池,你的能力再上一层

我们两清 提交于 2020-01-13 07:09:04
实战是检验真理的唯一标准,这里笔者整理了一些关于线程、多线程和线程池的面试题,一起学习和思考,这里的代码和例子是Java写的,主要是能够通用的介绍相关知识,编程语言只是一种工具,没有说哪种工具就绝对好,关键是使用工具的人,以及我们项目的具体需求,当我们掌握了真正的知识点之后,对于不同的语言,那只是语法的不一样。好啦不装X了,这个文章前端后端都可以看,祝看到的人都有个好的未来! 1、开启线程的三种方式? 继承Thread类,重写run()方法,在run()方法体中编写要完成的任务 new Thread().start(); 实现Runnable接口,实现run()方法 new Thread(new MyRunnable()).start(); 实现Callable接口MyCallable类,实现call()方法,使用FutureTask类来包装Callable对象,使用FutureTask对象作为Thread对象的target创建并启动线程;调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。 FutureTask < Integer > ft = new FutureTask < Integer > ( new MyCallable ( ) ) ; new Thread ( ft ) . start ( ) ; 2、run()和start()方法区别 run

alternatives for volatile array

不问归期 提交于 2020-01-13 05:16:07
问题 From other questions, I learned that the elements of a volatile array are not volatile. Only the reference itself is volatile. volatile[] int data; Thread A: data[4] = 457; Thread B: System.out.println(data[4]); Here, Thread B might never see the updated value. Which options/alternatives do I have to achieve the same thing? I would like to avoid having to synchronize the array, since it is hardly ever altered. However, it is being read a lot by some threads. Synchronizing it will very likely

高并发编程

浪子不回头ぞ 提交于 2020-01-13 03:35:43
(一)高并发编程基础知识 这里涉及到一些基础的概念,我重新捧起了一下《实战 Java 高并发程序设计》这一本书,感觉到心潮澎湃,这或许就是笔者叙述功底扎实的魅力吧,喜欢。对于并发的基础可以参照一下我之前写过的一篇博文: Java学习笔记(4)——并发基础 1)多线程和单线程的区别和联系? 答: 在单核 CPU 中,将 CPU 分为很小的时间片,在每一时刻只能有一个线程在执行,是一种微观上轮流占用 CPU 的机制。 多线程会存在线程上下文切换,会导致程序执行速度变慢,即采用一个拥有两个线程的进程执行所需要的时间比一个线程的进程执行两次所需要的时间要多一些。 结论:即采用多线程不会提高程序的执行速度,反而会降低速度,但是对于用户来说,可以减少用户的响应时间。 面试官:那使用多线程有什么优势? 解析:尽管面临很多挑战,多线程有一些优点仍然使得它一直被使用,而这些优点我们应该了解。 答: (1)资源利用率更好 想象一下,一个应用程序需要从本地文件系统中读取和处理文件的情景。比方说,从磁盘读取一个文件需要5秒,处理一个文件需要2秒。处理两个文件则需要: 1| 5秒读取文件A 2| 2秒处理文件A 3| 5秒读取文件B 4| 2秒处理文件B 5| --------------------- 6| 总共需要14秒 从磁盘中读取文件的时候,大部分的CPU时间用于等待磁盘去读取数据。在这段时间里

volatile和synchronized

六眼飞鱼酱① 提交于 2020-01-13 03:35:05
volatile是变量修饰符,而synchronized则是作用于代码,方法和变量。 int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;} 1.geti1()是得到储存在当前线程中i1的数值,而多个线程又多份i1变量的拷贝,这些i1可能不相同。(另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。) 在JAVA内存模型的,有main memory(主内存区域),存放着变量当前的准确值,每个线程也有自己的memory(例如寄存器),为了性能,一个线程会在自己的memory中保存要访问的变量的副本。这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory的值,或者main memory的值不一致的情况。因此实际上存在一种可能:main memory的值i1值是1,线程1里的i1是2,线程2里的i1值是3,这在线程1和线程2都改变了他们各自的i1值,而且这个改变还没来得及传给main memory 或其他线程时就会发生。 2.geti2() 得到的是main memory的i2数值。一个变量声明为volatile

volatile和synchronized

别等时光非礼了梦想. 提交于 2020-01-13 03:33:56
这个可能是最好的对比 volatile 和 synchronized 作用的文章了。 volatile 是一个变量修饰符,而 synchronized 是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。 int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;} geti1() 在 当前线程 中立即获取在 i1 变量中的值。线程可以获得变量的本地拷贝,而所获得的变量的值并不一定与其他线程所获得的值相同。特别是,如果其他的线程修改了 i1 的值,那么当前线程获得的 i1 的值可能与修改后的值有所差别。实际上, Java 有一种主内存的机制,使用一个主内存来保存变量当前的正确的值。线程将变量的值拷贝到自己独立的内存中,而这些线程的内存拷贝可能与主内存中的值不同。所以实际当中可能发生这样的情况,在主内存中 i1 的值为 1 ,线程 1 和线程 2 都更改了 i1 ,但是却没把更新的值传回给主内存或其他线程中,那么可能在线程 1 中 i1 的值为 2 ,线程 2 中 i1 的值却为 3 。 另一方面, geti2() 可以有效的从主内存中获取 i2 的值。一个 volatile