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

标签 java multithreading

我的理解是Java允许线程访问共享变量。通常,为了确保共享变量的更新一致,线程应通过获取对这些共享变量强制互斥的锁来确保它独占使用这些变量。如果字段被声明为 volatile ,在这种情况下,Java 内存模型将确保所有线程看到该变量的一致值。

在下面的程序中,tickectsAvailable是一个存储在堆上的共享变量,因为线程1和线程2是在同一个对象“obj”上创建的,线程1和线程2都可以访问obj

我试图了解何时使变量变为 volatile 。在这种情况下,正确的用例应该是使“ticketsAvailable”不稳定。我对 volatile 变量的理解正确吗?

我读到一篇文章说:出于性能原因,每个线程在处理变量时可能会将主内存中的变量复制到 CPU 缓存中。如果您的计算机包含多个 CPU,则每个线程可能在不同的 CPU 上运行。这意味着,每个线程都可以将变量复制到不同CPU的CPU缓存中

在这种情况下,如果我不将“ticketsAvailable”设置为 volatile ,那么如果我有多个线程在同一对象(“obj”)上工作(如果只有多个 CPU),则线程可能会从 CPU 缓存中读取更改?

只有当您的计算机包含多个 CPU 时才应该使用 Volatile 变量吗?但是如果我在同一个 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


        }

    }

    /** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
    public class MyClass {
        public static void main(String args[])
        {
               TicketBooking obj=new TicketBooking();

               Thread thread1=new Thread(obj,"Passenger1 Thread");
               Thread thread2=new Thread(obj,"Passenger2 Thread");

               thread1.start();
               thread2.start();

        }

    }

    /*OUTPUT

    Waiting to book ticket for : Passenger2 Thread
    Waiting to book ticket for : Passenger1 Thread
    Booking ticket for : Passenger2 Thread
    Ticket BOOKED for : Passenger2 Thread
    currently ticketsAvailable = 0
    Ticket NOT BOOKED for : Passenger1 Thread

    */

最佳答案

volatile 变量保证happen before relation 。如果只有一个线程正在写入,而所有其他线程都在读取变量,那么在这种情况下, volatile 变量可以确保线程安全。在其他场景中,您必须根据需要使用其他同步机制。

Should Volatile variable be used only when your computer contains multiple CPU's? But if i have multiple threads on same obj and one cpu how is it going to behave?

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

关于java - 线程上下文中的缓存是什么以及何时在 Java 中使用 volatile 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51803157/

相关文章:

java - opencv编辑图像使文字更清晰

C# 从调用线程外部的静态类访问函数

c# - 我如何从WhenAll(任务数组)中获取结果

java - DAO 如何映射 SQL 函数返回的字段?

java - 使用 Spring Boot "bootRun"启动的应用程序在包含 Gradle Vaadin 插件时导致 NoClassDefFoundError

java - 当线程中发生异常时,SchduledExecutorService 不执行 UncaughtExceptionHandler

java - 加速实体管理器3000条记录的提交

c++ - Qt:QList线程问题

java - RxAndroid : UI changes on Schedulers. io() 线程

c# - 在 Invoke/BeginInvoke 期间锁会发生什么情况? (事件派发)