W.r.t java线程,处理同步静态方法和非静态方法所用的时间会有什么不同吗?

W.r.t java线程,处理同步静态方法和非静态方法所用的时间会有什么不同吗?,java,multithreading,methods,static,Java,Multithreading,Methods,Static,考虑两类: Class A { public static synchronized void printA() { ...//.... } } Class B { public synchronized void printB() { ...//... } } 现在,假设我在printA和printB上都有一百万个线程。printA执行100万线程的速度会比printB快吗?反之亦然?或者不保证总执行时间 静态调用会更快,因为您的程序不需要通过对象

考虑两类:

Class A {

   public static synchronized void printA() {
    ...//....
   }
}

Class B {

   public synchronized void printB() {
   ...//...
   }
}

现在,假设我在printA和printB上都有一百万个线程。printA执行100万线程的速度会比printB快吗?反之亦然?或者不保证总执行时间

静态调用会更快,因为您的程序不需要通过对象来定位它们。因此,每次调用它们都会为您保存一个引用。

静态调用会更快,因为您的程序不需要通过对象来定位它们。因此,每次调用它们将为您保存一个引用。

这里的一个主要因素是您有多少不同的对象。静态方法将在
A.class
对象上同步,这意味着在给定时刻整个JVM中只有一个线程能够在
printA()
中(每个类都有与其关联的
class
实例)。实例方法将在特定对象上同步,这意味着许多线程可以同时调用
printB()
,每个线程都在自己的
B
实例上工作。当然,如果只有一个
B
实例,那么一次只允许一个线程运行
printB()

另一个主要因素是计算机的物理资源!旋转100万个线程并不能神奇地让CPU在相同的时间单位内完成100万倍的工作。事实上,它可能会降低您的程序的整体速度,因为每个线程都在您宝贵的4或8个内核上争夺时间(如果您将超线程考虑在内或在一个强大的服务器上运行它,可能会更多,但我打赌您不会有接近100万个内核)。每次一个线程胜出于之前运行的线程时,它都会引发上下文切换(“停止运行该线程,开始运行该线程”),这是非常昂贵的

如果您的操作是非常CPU密集型的,那么您不会得到比现有内核数量更好的提升。如果它们都在争夺一个公共资源(如磁盘I/O),您可能不会比只有一两个线程好多少,而且您甚至可能会看到更低的性能(如果每个线程在每次安排某项工作时都会导致磁盘查找到不同的位置)


基本上,假设你有8个内核,100万个线程和20个不同的
B
对象均匀地分布在这些线程中。使用
静态同步
方法,一次只允许其中一个使用
printA()
。使用instance
synchronized
方法,一次将允许20个不同的线程运行
printB()
(20个
B
实例中的每一个都有一个线程),其中一次只能运行8个线程。

这里的一个主要因素是您有多少不同的对象。静态方法将在
A.class
对象上同步,这意味着在给定时刻整个JVM中只有一个线程能够在
printA()
中(每个类都有与其关联的
class
实例)。实例方法将在特定对象上同步,这意味着许多线程可以同时调用
printB()
,每个线程都在自己的
B
实例上工作。当然,如果只有一个
B
实例,那么一次只允许一个线程运行
printB()

另一个主要因素是计算机的物理资源!旋转100万个线程并不能神奇地让CPU在相同的时间单位内完成100万倍的工作。事实上,它可能会降低您的程序的整体速度,因为每个线程都在您宝贵的4或8个内核上争夺时间(如果您将超线程考虑在内或在一个强大的服务器上运行它,可能会更多,但我打赌您不会有接近100万个内核)。每次一个线程胜出于之前运行的线程时,它都会引发上下文切换(“停止运行该线程,开始运行该线程”),这是非常昂贵的

如果您的操作是非常CPU密集型的,那么您不会得到比现有内核数量更好的提升。如果它们都在争夺一个公共资源(如磁盘I/O),您可能不会比只有一两个线程好多少,而且您甚至可能会看到更低的性能(如果每个线程在每次安排某项工作时都会导致磁盘查找到不同的位置)

基本上,假设你有8个内核,100万个线程和20个不同的
B
对象均匀地分布在这些线程中。使用
静态同步
方法,一次只允许其中一个使用
printA()
。使用instance
synchronized
方法,一次将允许20个不同的线程运行
printB()
(20个
B
实例中的每一个都有一个线程),其中一次只能运行8个线程。

这取决于具体情况

  • 同步静态方法和实例方法在语义上是不同的:前者在整个类上同步,而后者在特定实例上同步。因此,所有线程都在相同的资源上竞争
    printA()
    ,而
    printB()
    ,这取决于有多少
    B
    实例以及您如何决定使用哪个
    B
    实例等,在实例方法上同步不会比在静态方法上同步差

  • 除了资源争用之外,在调用实例方法时还存在虚拟表查找的因素。因此,如果您只有一个
    B
    实例,并且每个人都在为该实例调用
    printfB()
    (这使得资源争用方面相同),那么调用静态方法不会比调用实例方法更糟糕。(请注意,这并不意味着它总是更好,因为虚拟机具有灵活性