volatile关键字相信大家都不陌生,在多线程并发编程里面用的比较多。网上有很多分析,但到底用和不用有什么区别,会造成什么影响,实际的代码示例比较少。现在就用代码来针对分析一下
引用linux之父Torvalds的一句话 -- talk is cheap show me the code
程序思路如下,先让thread2跑起来,进入一个循环,而这个循环也不是严格意义上的死循环,只不过解开死循环的key不在该线程本身,而是被另一个线程控制着。而这里的key有2个,一个是加了volatile,一个是没加,会有什么效果呢?运行下看看先(哇塞,用了句倒装)
package com.cug.thread; class VolatileExample { int x = 0; volatile int b = 0; private void write() { x = 5; b = 1; } private void read() { while (x != 5) { } /*while (b != 1) { }*/ } public static void main(String[] args) throws Exception { final VolatileExample example = new VolatileExample(); Thread thread1 = new Thread(new Runnable() { public void run() { try { //确保Thread2在Thread1之前执行 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } example.write(); } }); Thread thread2 = new Thread(new Runnable() { public void run() { example.read(); } }); thread2.start(); thread1.start(); } }
执行完了,大家会发现,当用x作为key的时候,不顶事儿,还是死循环。但用b作为key的时候,循环很快被解开,得到了我们预计的效果。
好了,有了实例,我们再带着问题好好分析。
首先我们需要简单说明一下java内存模型(java memory model)
根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。
每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。
Java语言规范中也有指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才将私有拷贝与共享内存中的原始值进行比较。
通俗点说就是,这里的2个变量
int x = 0; volatile int b = 0;
x位于工作内存中,而b位于主存中。
再通俗点讲就是,thread1有一个自己的x,thread2有一个自己的x,而他们只有一个共享的b
很多人拿volatile和synchronzed说事,比较效率啊什么的,其实这有什么好比的,两个人负责的功能点都不一样。有的地方可能确实可以用volatile代替synchronized,也确实能提升一些效率,但你有考虑过你代码的可读性吗?不要为了一时的效率,而牺牲别人对你代码意思的误解。(之前看过一个人写了个for循环,循环了50000次,问他干嘛这么写,他说他为了让程序在这稍微停一会)。
好了好了,不跑题,我们接着说
synchronized是同步的意思,同步代码块,同步函数等,意思就是让一小块独立成一个单元来执行。
而volatile呢,它的作用其实就是一个共享操作、集中管理的作用。不知道大家有没有看过火影,火影里面有一个Team很厉害叫佩恩(又快跑了。。),他是由6个人组成的,他有一个特殊点就是6个人可以交换视野,每个人都能看到另外5个人看到的东西。volatile扮演的就是这么一个视野的作用,共享属性,同步更新。对加了volatile关键字的属性,不会被加载到每个线程的工作内存中,而是在主存中修改查看
如有说的不好的不全的,大家可以到这里去看看,感觉这个还是很权威啊,我的只能叫小众,看合不合您的胃口了
相关推荐
一、`volatile`关键字的语义分析 1. **保证可见性**:当一个线程修改了`volatile`变量的值,其他所有线程都能立即看到这个变化。这是因为`volatile`变量的写操作会强制将当前处理器的缓存行写回主内存,其他处理器...
2. **单例模式的双重检查锁定**:在实现双检锁时,`volatile`用来确保`Singleton`实例被正确初始化后才可见。 **示例分析**: 在给出的例子中,`VolatileWithoutUsage`类的`count`变量没有使用`volatile`修饰,导致...
通过实例分析,学习者能够掌握如何在面对硬件交互和中断服务等场景时,正确地使用 `volatile` 来保证程序的正确性和可靠性。同时,通过文字讲解,还能加深对 `volatile` 工作原理的理解,这对于任何从事单片机开发的...
Volatile关键字的作用就是确保工作内存中的变量值及时同步到主内存,并且其他线程读取时能获取到最新的值。 Volatile的两个主要特性是: 1. **内存可见性**:当一个线程修改了Volatile变量的值,其他线程可以立即...
- **demo9**:可能通过volatile关键字实现线程间变量的即时通信。 - **demo5**:可能对比了synchronized和volatile在解决线程安全问题上的差异。 - **demo12**:可能探讨了volatile的使用限制,如非原子性操作的问题...
本文实例讲述了C#中volatile与lock用法,分享给大家供大家参考。具体分析如下: 一、C#中volatile volatile是C#中用于控制同步的关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问...
在Java并发编程中,volatile关键字扮演着至关重要的角色,它提供了线程间的可见性和部分内存屏障,以确保共享变量在多线程环境下的正确性。然而,在实际应用中,开发者可能会遇到一些意料之外的问题,这通常是因为对...
Java编程语言中的volatile关键字在多线程环境下扮演着至关重要的角色,它提供了内存可见性和一定的原子性保证。首先,我们来深入理解volatile关键字的作用。 1. **内存可见性**:volatile保证了变量在被修改后,...
本报告将深入探讨Java中实现线程安全的策略、关键字以及集合类,并通过实例分析线程安全问题。 1. **线程安全的基本概念** 线程安全的定义是指在多线程环境下,某个对象或代码片段的行为是预期的,不会出现数据不...
2. 实例分析:这些方法通常与synchronized关键字配合使用,确保在调用wait()和notify()时,只有一个线程持有对象锁。 三、线程让步和休眠 线程让步和休眠是控制线程执行顺序和时间的手段。 1. 线程让步:Yield()...
- 其他关键字:如void、static、final、abstract、native、transient、volatile等,各有特定用途。 2. Java关键字应用示例: - `public class HelloWorld {` 这行代码定义了一个公共类HelloWorld,可供其他类访问...
1. **volatile关键字**:声明为volatile的变量,在被线程修改后会立刻刷新到主内存中,其他线程在读取时也会强制从主内存中读取最新的值。 2. **synchronized关键字**:同步代码块不仅提供了锁机制,还确保了锁释放...
- **volatile关键字**:通过在变量声明前加上`volatile`关键字,可以确保任何时刻只有一个线程能修改该变量,并且修改后的值能立即对其他线程可见。 - **synchronized关键字**:通过在方法或代码块上使用`...
volatile关键字保证了多线程环境下变量的可见性,避免了指令重排序,从而保证了单例的正确创建。 此外,单例模式还有几种变体,比如静态内部类单例和枚举单例。静态内部类单例利用Java类加载机制保证了线程安全,而...
总的来说,这篇文章通过实例和分析,揭示了Java DCL模式的一些常见误解,并强调了深入理解JMM对于开发高效、可靠的并发代码的重要性。通过这种方式,开发者可以更好地掌握如何在多线程环境中正确地实现单例模式。
双检锁/双重校验锁(DCL,即double-checked locking)是一种常用的实现方式,它结合了volatile关键字和synchronized,保证了线程安全的单例创建。 3. 管道/Pipe模式:通过Pipe或Channel实现线程间的通信,如在NIO中,...
同时,通过内存屏障和volatile关键字,JMM还提供了数据的有序性保证,防止指令重排序带来的问题。 4. **volatile关键字**:volatile修饰的变量保证了多线程环境下的可见性和有序性,但不保证原子性。当多个线程同时...
通过了解和掌握`synchronized`关键字、Lock接口、volatile关键字以及原子类等多种同步机制,开发者可以更好地设计出高效且稳定的多线程程序。此外,还需要结合具体的应用场景选择最适合的同步策略,以达到最佳的效果...
volatile关键字可以解决这个问题,它确保对变量的修改对所有线程都是可见的。 6. 原子性:如果一个操作不能被分割成多个步骤,那么它就是原子的。Java提供了一些原子类,如AtomicInteger,保证了原子性操作。 7. ...
volatile关键字用于修饰变量,确保多线程环境下的可见性和有序性,即当一个线程修改了volatile变量,其他线程能立即看到这一变化,避免数据不一致的问题。 6. static 关键字的用途有哪些? static关键字可以用于...