volatile

Java线程面试题 Top 50 (转载)

Deadly 提交于 2020-02-26 10:06:30
 本文由 ImportNew - 李 广 翻译自 javarevisited 。欢迎加入 Java小组 。转载请参见文章末尾的要求。   不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者精通多线程技术并且有丰富的Java程序开发、调试、优化经验,所以线程相关的问题在面试中经常会被提到。   在典型的Java面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程, 如何创建线程,用什么方式创建线程比较好(比如: 继承thread类还是调用Runnable接口 ),然后逐渐问到并发问题像在Java并发编程的过程中遇到了什么挑战,Java内存模型,JDK1.5引入了哪些更高阶的并发工具,并发编程常用的 设计模式 ,经典多线程问题如生产者消费者,哲学家就餐,读写器或者简单的有界缓冲区问题。仅仅知道线程的基本概念是远远不够的, 你必须知道如何处理 死锁 , 竞态条件 ,内存冲突和线程安全等并发问题。掌握了这些技巧,你就可以轻松应对多线程和并发面试了。   许多Java程序员在面试前才会去看面试题,这很正常。因为收集面试题和练习很花时间,所以我从许多面试者那里收集了Java多线程和并发相关的50个热门问题

2、原子性、可见性与有序性

别来无恙 提交于 2020-02-26 05:23:08
原子性(Atomicity) :由Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write,我们大致可以认为 基本类型的访问读写是具备原子性的。 如果应用场景还需要一个更大范围的原子性保证,Java内存模型还提供了lock和unlock操作来满足这种需求。 可见性(Visibility) :可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。Java内存模型是通过在变量修改后将 新值同步到主内存,无论是普通变量还是volatile变量都是如此,普通变量与volatile变量的区别是,volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。因此,可以说volatile保证了多线程操作时变量的可见性,而普通变量不能保证这一点。 有序性(Ordering) :Java程序天然的有序性可以总结为一句话:如果本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。前半句是指“线程内表现为串行的语义”,后半句是指“指令重排序”现象和“工作内存与主内存同步延迟”现象。 来源: https://www.cnblogs.com/feijishuo/p/4546274.html

🔥史上最全的Java并发系列之Java并发机制的底层实现原理

社会主义新天地 提交于 2020-02-26 05:10:55
并发编程的3个基本概念 原子性 定义: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。Java中的原子性操作包括: a. 基本类型的读取和赋值操作,且赋值必须是数字赋值给变量,变量之间的相互赋值不是原子性操作。 b.所有引用reference的赋值操作 c.java.concurrent.Atomic.* 包中所有类的一切操作 可见性 定义:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 在多线程环境下,一个线程对共享变量的操作对其他线程是不可见的。Java提供了volatile来保证可见性,当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,其他线程读取共享变量时,会直接从主内存中读取。当然,synchronize和Lock都可以保证可见性。synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。 有序性 定义

volatile

爱⌒轻易说出口 提交于 2020-02-25 15:59:59
volatile是什么 对于volatile, <The Java Language Specification Third Edition>是这样描述的 “A field may be declared volatile, in which case the Java memory model ensures that all threads see a consistent value for the variable.” 意思是,如果一个变量声明为volatile, Java 内存模型保证所有的线程看到这个变量的值是一致的。 “… the volatile modifier guarantees that any thread that reads a field will see the most recently written value.” - Josh Bloch Josh Bloch 说 ”volatile描述符保证任意一个程序读取的是最新写的值“ 有人会问,内存不是存放变量值的地方吗,线程T1写,然后线程T2读,怎么会出现不一致的情况呢。 缓存 实际上内存不是唯一存储变量的地方。CPU往往会把变量的值存放到缓存中。假如一个CPU,即使在多线程环境下也不会出现值不一致的情况。但是,在多CPU,或者多核CPU的情况就不是这样了。如下图所示,在多个CPU情况下

3、先行发生原则

若如初见. 提交于 2020-02-24 17:51:19
如果Java内存模型中所有的有序性都仅仅依靠volatile和synchronized来完成,那么一些操作将会变得很繁琐,但是我们在编写Java程序时并没有感觉到这一点,这是因为Java语言中有一个”先行发生(happens-before)“的原则。这个原则非常重要,它是判断数据是否存在竞争、线程是否安全的主要依据。 下面是Java内存模型下一些“天然的”先行发生关系,这些先行发生关系无需任何同步协助就已经存在,可以在编码中直接使用。如果两个操作之间的关系不在此例,并且无法从下列规则推导出来的话,它们就没有顺序性保障,虚拟机可以对它们随意地进行重排序。 线程锁定规则 :一个unlock操作先行发生于在后面对同一个锁的lock操作。这里必须强调的是同一个锁,而“后面”是指时间上的先后顺序。 volatile变量规则 :对一个volatile变量的写操作先行发生于在后面对这个变量的读操作,这里的“后面”同样是指时间上的先后顺序。 线程启动规则 :线程中的所有操作都先行于对此线程的终止检测,我们可以通过Thread.join方法结束、Thread.isAlive的返回值等手段检测到线程已经终止执行。 线程中断规则 :对线程interrupt方法的调用先行于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted方法检测到是否发生中断。 对象终结规则

cmd中java的编译命令——java和javac、javap

萝らか妹 提交于 2020-02-24 16:53:24
最近重新复习了一下java基础,这里便讲讲对于一个类文件如何编译、运行、反编译的。也让自己加深一下印象 如题,首先我们在桌面,开始->运行->键入cmd 回车,进入windows命令行。进入如图所示的画面: 可知,当前默认目录为C盘Users文件夹下的Administrator文件夹。一般而言,我们习惯改变当前目录。由于windows有磁盘分区,若要跳到其他磁盘,例如E盘,有几种方法: 1、输入命令: pushd 路径(此命令可将当前目录设为所希望的任一个已存在的路径) 2、输入命令: e: 转移到e盘,然后再输入 cd 转移到所希望的已知路径。 如图: 希望在windows命令行下使用javac、java、javap等命令,那么当前电脑必须安装了jdk,并且将jdk的bin目录添加到环境变量path下了。这个不用多说。那么让我们看一下如何使用javac、java、javap吧。 一、javac javac是用来编译.java文件的。命令行下直接输入javac可以看到大量提示信息,提示javac命令的用法,我只知道常用的。 javac -d destdir srcFile 其中:1、-d destdir是用来指定存放编译生成的.class文件的路径。(若此选项省略,那么默认在当前目录下生成.class文件,并且没有生成包文件夹;当前目录可以用“.”来表示,即:javac -d .

2018-2-24 牛客试题复盘

和自甴很熟 提交于 2020-02-24 14:18:00
1、使用mvc模式设计的web应用程序具有以下优点,除了? D A、可维护行强 B、可扩展性强 C、代码重复少 D、大大减少代码量 2、关于依赖注入,下列选项中说法错误的是(B) A、依赖注入能够独立开发各组件,然后根据组件间关系进行组装 B、依赖注入使组件之间相互依赖,相互制约 C、依赖注入提供使用接口编程 D、依赖注入指对象在使用时动态注入 解析: 依赖注入的动机就是减少组件之间的耦合度,使开发更为简洁。 3、下列说法正确的是( C) A、volatile,synchronized 都可以修改变量,方法以及代码块 B、volatile,synchronized 在多线程中都会存在阻塞问题 C、volatile能保证数据的可见性,但不能完全保证数据的原子性,synchronized即保证了数据的可见性也保证了原子性 D、volatile解决的是变量在多个线程之间的可见性、原子性,而sychroized解决的是多个线程之间访问资源的同步性 解析: synchronized关键字和volatile关键字比较: volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1

synchronized 与 volatile

爷,独闯天下 提交于 2020-02-24 07:47:35
synchronized 与 volatile: 可见性 :一个线程对共享变量的修改,能够及时的被其他线程看到 所有的变量都储存在主内存中,每个线程独有自己独立的工作内存,里面保存着主内存中该变量的拷贝副本 线程对共享变量的操作都必须在自己的工作内存中进行不能直接在主内存中读写。不同线程中的变量值需要通过主内存传递。 Synchronized :可以实现原子性(同步)、可见性。线程解锁前必须把共享变量的最新值刷新到主内存中。加锁时会清空工作内存中共享变量的值,从而使用共享变量时会重新从主内存中读取最新变量值(加锁解锁需要是同一把锁)。 重排序:代码书写顺序与实际执行顺序不一致 是编译器或者处理器为提高程序执行性能而做的优化 共享变量线程间不可见原因:重排序、线程交叉执行、共享变量值更新后没有在工作内存和主内存间及时更新 Synchronized 加到方法上时默认使用当前对象锁。方法一旦执行,就会独占该锁,一直到从该方法返回时或者出现异常时 jvm才将锁释放,此后被阻塞的线程方能获得该锁,从而重新进入可执行状态。 运行结果多运行几次会发现 如果不加synchronized 多个线程会存在交叉运行如:002、022或者线程的先后顺序会变化如002、222。 加了synchronized后虽然线程的先后顺序会变化但会一直到从该方法返回。 Volitale

linux C 中的volatile使用

孤街醉人 提交于 2020-02-23 16:40:25
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 1). 一个参数既可以是const还可以是volatile吗?解释为什么。 2). 一个指针可以是volatile 吗?解释为什么。 3). 下面的函数有什么错误: int square(volatile int *ptr) { return *ptr * *ptr; } 下面是答案: 1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变

Java并发编程实战3章

喜你入骨 提交于 2020-02-23 13:17:29
1.同步包括两方面:原子性和可见性。 2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据。 Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的long和double变量,JVM允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用关键字volatile来声明它们,或者用锁保护起来。 加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步。 下面的代码是书中例子,如果多线程访问这个类,就存在可见性问题,但是如何测试得到比如输出为0的结果或者程序无法终止?求赐教! public class NoVisibility { private static boolean ready = false; private static int number = 0; public static class ReaderThread extends Thread { public