企业网站设计建设长春,外国购物网站大全,服务器搭建云电脑,长沙城乡建设网站目录 1. volatile
1.1 volatile关键字的作用
1.1.1 变量可见性
1.1.2 禁止指令重排序
1.2 volatile可见性案例
1.3 volatile非原子性案例
1.4 volatile 禁止重排序
1.5 volatile 日常使用场景
送书活动 1. volatile
在并发编程中#xff0c;多线程操作共享的变量时多线程操作共享的变量时可能会导致线程安全问题如数据竞争、可见性问题等。为了解决这些问题Java提供了JUCjava.util.concurrent工具包其中包含了很多用于处理并发编程的工具类和接口。在JUC中volatile是一个关键字它可以用于修饰变量用来确保变量的可见性和禁止指令重排序从而在一定程度上解决线程安全问题。
1.1 volatile关键字的作用
1.1.1 变量可见性
在多线程环境下如果一个线程修改了共享变量的值其他线程可能由于线程间的数据不一致性而看不到该变量的最新值。这种问题称为“变量不可见性”或“可见性问题”。
volatile关键字可以确保被修饰的变量对所有线程可见。当一个线程修改了volatile变量的值其他线程立即能够看到修改后的最新值而不会使用缓存中的旧值。
1.1.2 禁止指令重排序
在JVMJava虚拟机中为了优化性能编译器和处理器可能会对指令进行重排序。在单线程环境下这种重排序不会影响程序的执行结果。然而在多线程环境下指令重排序可能会导致线程安全问题。
volatile关键字可以防止指令重排序确保被修饰的变量按照代码中的顺序执行。
1.2 volatile可见性案例
public class VolatileExample {private static volatile boolean flag false;public static void main(String[] args) {new Thread(() - {while (!flag) {System.out.println(Waiting for the flag to be true...);}System.out.println(Flag is now true. Exiting the thread.);}).start();try {Thread.sleep(1000); // 确保主线程在子线程之前执行} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Setting the flag to true...);flag true;}
}在上面的示例中我们创建了一个VolatileExample类并声明了一个volatile类型的flag变量。在主线程中我们启动一个新的子线程该子线程会不断地检查flag变量的值直到flag变为true时子线程退出。
在主线程中我们将flag变量设置为true。由于flag变量被声明为volatile类型子线程能够及时看到flag的最新值从而退出循环输出“Flag is now true. Exiting the thread.”。
这个示例演示了volatile关键字的作用确保了flag变量的可见性。如果我们没有使用volatile关键字子线程可能会一直循环下去因为它看不到主线程对flag的修改。 1.3 volatile非原子性案例
public class Test {public static void main(String[] args) throws InterruptedException {VolatileAtomicityExample example new VolatileAtomicityExample();for(int i1;i100;i){new Thread(()-{for(int j1;j1000;j)example.increment();},String.valueOf(i)).start();}TimeUnit.SECONDS.sleep(2);System.out.println(example.getCount());}}
class VolatileAtomicityExample {volatile int count 0;public void increment() {count;}public int getCount() {return count;}
}我们创建了一个VolatileAtomicityExample类其中的成员变量count被声明为volatile类型。然后我们创建了100个线程每个线程分别执行1000次increment()操作对count进行自增。最后我们在主线程中打印count的最终值。以上示例中的输出结果可能会因为运行时的不确定性而有所不同。每次运行时可能得到不同的结果但通常结果都小于100000。为了解决这个问题我们需要使用synchronized关键字或其他线程安全机制来确保increment()方法的原子性。
这是什么原因呢 对于volatile变量具备可见性JVM只是保证从主内存加载到线程工作内存的值是最新的也仅是数据加载时是最新的。但是多线程环境下数据计算和数据赋值操作可能多次出现若数据在加载之后若主内存volatile修饰变量发生修改之后线程工作内存中的操作将会作废去读主内存最新值操作出现写丢失问题。即各线程私有内存和主内存公共内存中变量不同步进而导致数据不一致。由此可见volatile解决的是变量读时的可见性问题但无法保证原子性对于多线程修改主内存共享变量的场景必须使用加锁同步。
1.4 volatile 禁止重排序
内存屏障是一种硬件指令或者编译器指令用于控制内存操作的顺序以确保多线程环境下的内存可见性和正确的执行顺序。
内存屏障分为两种类型 内存读屏障Load Barrier它是一个特殊的硬件或者编译器指令用于保证在内存读取操作之前所有的先行写操作都已经完成并且其结果对当前线程可见。也就是说读屏障可以防止后续读取指令重排序到读屏障之前的位置。 内存写屏障Store Barrier它是一个特殊的硬件或者编译器指令用于保证在内存写入操作之前所有的先行写操作和写屏障之前的写操作都已经完成并且其结果对其他线程可见。也就是说写屏障可以防止前面的写入指令重排序到写屏障之后的位置。
volatile关键字通过内存屏障来保证变量的读写操作不会被重排序。具体来说对于volatile变量的写操作在写入变量之后会插入写屏障这样可以防止其他指令重排序到写屏障之前。类似地对于volatile变量的读操作在读取变量之前会插入读屏障这样可以防止其他指令重排序到读屏障之前。
通过这种方式volatile关键字确保了对变量的读写操作具有一定的有序性从而保证了多线程环境下的内存可见性和正确的执行顺序。
1.5 volatile 日常使用场景
状态标志当一个线程修改了某个状态标志其他线程需要立即看到最新的状态。这时可以使用volatile关键字修饰状态标志保证其在多线程之间的可见性。例如
public class Task implements Runnable {private volatile boolean isRunning true;Overridepublic void run() {while (isRunning) {// 执行任务逻辑}}public void stop() {isRunning false;}
}双重检查锁定Double-Checked Locking在多线程环境下当需要延迟初始化一个对象时为了避免重复初始化常常使用双重检查锁定。在这种情况下需要使用volatile关键字来确保对象在多线程环境中的可见性。例如
public class Singleton {private volatile static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance null) {synchronized (Singleton.class) {if (instance null) {instance new Singleton();}}}return instance;}
}在上述代码中我们实现了一个简单的单例模式。在getInstance()方法中我们使用双重检查锁定来实现延迟初始化确保只有在instance为空时才创建新的Singleton实例。
然而在多线程环境下由于指令重排序的存在可能会导致以下问题 对象引用不为空但尚未初始化在线程A执行完instance new Singleton();这一行之前可能发生指令重排序导致instance的引用不为空但是Singleton实例的初始化还未完成。这样线程B在执行return instance;时就会得到一个尚未初始化的对象导致错误。 可见性问题指令重排序也可能导致线程B无法及时看到线程A的初始化操作。例如线程A对instance的赋值可能被重排到线程A的后面执行从而线程B在读取instance时得到一个旧的引用无法感知线程A的初始化操作。
为了解决这个问题需要在创建Singleton实例时使用volatile关键字来保证对象的可见性和禁止指令重排序。 送书活动
《硅基物语·我是灵魂画手》 当AI遇上绘画会打开怎样的奇妙世界?
用ChatGPTMidjourney西出人类的灵魂与梦想
用StableDiffusionD-ID画出青春绚丽的渴望
激活每个人隐藏的绘画天赋
人人都能成为顶尖绘画大师 ChatGPTMidjourncyStableDiffusionD-IDRunwayGen-l
爆火软件全流程协作
掌据AI绘商技巧
解锁超全绘画关键司
讲解创作底层逻辑
一本书讲透AI绘画全流程 内容简介 一本将AI绘画讲透的探秘指南通过丰富的实践案例操作通俗易懂地讲述AI绘画的生成步骤生动展现了AI绘画的魔法魅力。从历史到未来跨越百年时空从理论到实践讲述案例操作:从技术到哲学穿越多个维度从语言到绘画落地实战演练。AI绘画的诞生引发了奇点降临点亮了AGI(通用人工智能)并涉及 Prompt、风格技术细节、多模态交互AIGC等一系列详细讲解。让您轻松掌握生图技巧创造出独特的艺术作品书写属于自己的艺术时代。 当当网链接http://product.dangdang.com/29601870.html 关注博主、点赞、收藏、 评论区评论 即可参与送书活动