且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

单例 Bean 如何服务并发请求?

更新时间:2023-11-13 13:49:28

Saravan Kumar,

Saravan Kumar,

我了解您提出问题的动机.在我开始研究编译器之前,我也有一个非常相似的想了解 Java 虚拟机的内部结构.

I understand the motivation behind your question. Before I started working on compilers, I also had a very similar wanting to know the internals of the Java Virtual Machine.

首先,我对你的问题印象深刻.为了解决您的问题,需要有几点区别和理解.首先:单例模式,有时甚至称为反模式,确保只有一个此类的实例可用于 JVM(Java 虚拟机).这意味着我们本质上是将全局状态引入应用程序.我知道你明白这一点,但这只是一个澄清点.

First of all, I'm impressed by your question. There needs to be a couple of points of distinctions and understanding in order to solve your question. Firstly: A Singleton pattern, or sometimes even called an anti-pattern, ensures that there is only one instance of this class available to the JVM(Java Virtual Machine). This means we are essentially introducing a global state into an application. I know you understand this, but it is just a point of clarification.

现在是内部结构.

当我们创建一个类的实例时,我们正在创建一个驻留在 JVM 共享内存中的对象.现在,这些线程正在独立执行对这些实例进行操作的代码.每个线程都有一个工作内存,它保存所有线程之间共享的主内存中的数据.这是对您创建的 Singleton 对象的引用所在的位置.本质上,正在发生的事情是生成的代表您创建的单例对象的字节码正在这些线程中的每一个线程上执行.

When we create an instance of a class, we are creating an object that is residing in JVM's shared memory. Now, these threads are independently executing code that operates on these instances. Each thread has a working memory, in which it keeps data from the main memory that are shared between all threads. This is where the reference to the Singleton object you have created resides. Essentially what is happening is that the bytecode which was generated and is representative of the singleton object you created is being executed on each one of these threads.

现在内部情况如下:

每个 JVM 线程都有一个私有 JVM 堆栈,与线程同时创建.现在,JVM 有一个在所有 JVM 线程之间共享的堆.堆是为所有类实例和数组分配内存的运行时数据区域.堆是在 VM 启动时创建的.当您的线程请求单例实例时,它将指向此单例的字节码所在的堆中的引用.它将执行适当的代码.在您的情况下,它将为第一个请求执行第一个方法,为第二个请求执行第二个方法.它能够这样做是因为没有锁或限制阻止编译器将程序计数器指向堆中分配此实例的区域.Singleton 类对 Java 虚拟机的唯一限制是它在该类的堆中只能有一个实例.就是这样.除此之外,您可以从您的方法中引用它 100 次,编译器将指向相同的字节码并简单地执行它.这就是为什么我们通常希望 Singleton 类是无状态的,因为如果我们有任何线程访问它,我们不希望内部变量因为缺乏并发控制而发生变异.

Each JVM thread has a private JVM stack, created at the same time as the thread. Now, The JVM has a heap that is shared among all JVM threads. The heap is the runtime data area from which memory for all class instances and arrays is allocated. The heap is created on VM start-up. When your thread requests the singleton instance, it is going to point to a reference in the heap where the bytecode for this Singleton resides. It is going to execute the appropriate code. In your case, it is going to execute the first method for the first request and the second method for the second request. It's able to do this because there are no locks or restriction preventing the compiler from pointing the program counter to the area in the heap where this instance is allocated. The only restriction that the Singleton class puts on the Java Virtual Machine is that it can have only one instance in the heap of this class. That's simply it. Other than that, you can refer to it 100x times from your method, the compiler is going to point to the same bytecode and simply execute it. This is why we typically want the Singleton class to be stateless because if we any thread access it, we don't want internal variables to be mutated because of the lack of concurrency control.

如果您有任何问题,请告诉我!

Please let me know if you have any questions!