为了账号安全,请及时绑定邮箱和手机立即绑定

什么是线程上下文中的缓存以及何时在 Java 中使用 volatile 关键字?

什么是线程上下文中的缓存以及何时在 Java 中使用 volatile 关键字?

慕容森 2021-07-09 18:11:48
我的理解是 Java 允许线程访问共享变量。通常,为了确保共享变量持续更新,线程应该通过获取对这些共享变量强制互斥的锁来确保它独占使用这些变量。如果一个字段被声明为 volatile,在这种情况下,Java 内存模型确保所有线程看到变量的一致值。在下面的程序中,ticectsAvailable是一个存储在堆上的共享变量,因为 thread1 和 thread2 是在同一个对象“ obj ”上创建的,所以 thread1 和 thread2 都可以访问 obj我试图了解何时使变量变得易变。在这种情况下,正确的用例将在这里使“ticketsAvailable”变得不稳定。我对 volatile 变量的理解正确吗?我读过一篇文章说:出于性能原因,每个线程在处理变量时可能会将变量从主内存复制到 CPU 缓存中。如果您的计算机包含多个 CPU,则每个线程可能运行在不同的 CPU 上。这意味着,每个线程都可以将变量复制到不同 CPU 的 CPU 缓存中在这种情况下,如果我不使“tickectsAvailable”不稳定,如果我有多个线程处理同一对象(“obj”),并且只有一个以上的 CPU,那么线程可能会从 CPU 缓存中读取更改?仅当您的计算机包含多个 CPU 时才应使用易失性变量吗?但是,如果我在同一个 obj 和一个 cpu 上有多个线程,它将如何表现?class TicketBooking implements Runnable{        int ticketsAvailable=1;        public void run(){               System.out.println("Waiting to book ticket for : "+Thread.currentThread().getName());               synchronized (this) {                      if(ticketsAvailable>0){                            System.out.println("Booking ticket for : "+Thread.currentThread().getName());                            //Let's say system takes some time in booking ticket (here we have taken 1 second time)                            try{                                   Thread.sleep(1000);                             }catch(Exception e){}                            ticketsAvailable--;                            System.out.println("Ticket BOOKED for : "+ Thread.currentThread().getName());                            System.out.println("currently ticketsAvailable = "+ticketsAvailable);                      }                      else{                            System.out.println("Ticket NOT BOOKED for : "+                                       Thread.currentThread().getName());                      }               }//End synchronization block        }    }
查看完整描述

2 回答

?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

仅当您的计算机包含多个 CPU 时才应使用易失性变量吗?

除非您正在为嵌入式系统编写代码,否则针对特定硬件平台优化您的代码可能是在浪费您的时间。从长远来看,这甚至可能是一个代价高昂的错误。

如果您正在编写 Java 代码,那么您很可能正在编写服务、Web 应用程序、移动应用程序或桌面应用程序。如果您正在编写任何这些内容,那么您的目标应该是通用 Java 平台,或者 Java 平台和某些特定的 SDK 或框架。帮自己一个忙,不要担心任何电脑或手机的品牌和型号。

如果一个字段被声明为 volatile,... Java ... 确保所有线程看到变量的一致值

每当你使用“一致”这个词时,你应该问自己,“与什么一致 ”

如果将单个变量标记为volatile,那么所有线程都会看到该变量的值与自身一致。也就是说,如果您有一个double d=0.0;,并且线程 A 设置了d=1.0;,并且线程 Bsystem.out.println(d);大约在同一时间调用,则线程 B 保证打印0.01.0。它永远不会打印任何其他值。

也许更重要的是,如果一个 volatile 变量被更新多次,那么所有线程将就更新发生的一致顺序达成一致。

但是,如果您希望多个变量彼此一致,那么您应该使用synchronized块或java.util.concurrent.locks.ReentrantLock对象来保护该组变量,而忘记了volatile.

每个线程都可以将变量从主内存复制到 CPU 缓存中...

Java 中没有“缓存”。Java 有它的内存模型。CPU 缓存是内存模型背后的隐藏原因。如果您正在为某个特定的计算机平台实现 JVM,那么希望 Java 内存模型能够让您自由地利用平台的缓存系统为您带来好处。

如果您正在为 Java 平台编写代码,那么您应该首先担心 Java 内存模型,以及您的程序在面对它时是否会正确运行。学习高速缓存系统是一项课外活动,它可以帮助您更好地理解 Java 为何如此。


查看完整回答
反对 回复 2021-07-14
?
回首忆惘然

TA贡献1847条经验 获得超11个赞

可变变量保证发生在关系之前。如果只有一个线程正在写入而所有其他线程正在读取一个变量,那么在这种情况下 volatile 变量可确保线程安全。在其他情况下,您必须根据需要使用其他同步机制。

仅当您的计算机包含多个 CPU 时才应使用易失性变量吗?但是,如果我在同一个 obj 和一个 cpu 上有多个线程,它将如何表现?

操作系统调度程序为每个线程分配 CPU。每个内核可以处理一个或多个线程取决于硬件能力。可变变量是语言内部的抽象,它与硬件功能没有任何直接关系。


查看完整回答
反对 回复 2021-07-14
  • 2 回答
  • 0 关注
  • 190 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信