jvm 多个线程如何并行执行同一个方法?

atmip9wb  于 2023-02-16  发布在  其他
关注(0)|答案(1)|浏览(169)

在阅读关于Spring单例无状态bean如何服务多个请求的this文章时,我一直在思考这个问题,这是作者的主要观点:
当线程请求单例bean时,它将引用(在堆栈中引用变量的帮助下)堆中单例bean的字节码。因此,多个线程可以同时引用单例bean。编译器将指向相同的字节码,然后简单地执行它,并将方法特定的值分别存储在堆栈中相应的块中。
这篇文章不错,但是它缺少了一些关于线程如何执行字节码的关键细节。每个线程都有自己的栈,栈包含帧,帧包含返回值,局部变量,操作数栈和当前类常量池引用。所有类都被加载到方法区,每个类数据存储常量和方法代码。所以我们只有一个地方有方法代码。因此,单行法(后来在JVM中称为字节码)只能由CPU的一个内核上的一个线程执行。方法中的同一行代码不能由两个不同的线程在两个不同的内核上同时执行,但方法中的两行不同代码可以由两个不同的线程在两个不同的内核上同时执行。并且如果没有其它线程执行方法的第一行,则每个线程可以开始执行方法。

mzillmmw

mzillmmw1#

所以我们只有一个地方有方法代码。
是的。
因此,一行方法(后面是JVM中的字节码)只能由一个CPU核上的一个线程执行。
这是不正确的。程序内存由所有线程共享,这包括类和字节码。类在 * 加载 * 时被锁定,但在没有使用特定同步基元的情况下执行或引用时不会被锁定。
两个不同内核上的两个不同线程不能同时执行同一行方法。
没有强制执行此限制的任何内容。
并且如果没有其它线程执行方法的第一行,则每个线程可以开始执行方法。
只有当一个方法被标记为synchronized,并且两个线程锁定在同一个对象示例上,或者该方法是静态的,这才是真的。

public class Foo {
   // many threads can be running bar() concurrently
   public void bar() {
      ...
   }

   // threads that are using the same instance of Foo can only execute
   // synchronized baz() and other synchronized methods one at a time.
   // Threads using other instances can execute baz() concurrently
   public synchronized void baz() {
      ...
   }

   // threads that are in the same classloader can only execute static
   // synchronized bing() and other static synchronized methods one at a time
   // because the class is being synchronized
   public static synchronized void bing() {
      ...
   }
}

这并不涉及内存共享、消息传递或线程编程涉及的其他复杂概念。

相关问题