关于java:Object vs byte [0] as lock

Object vs byte[0] as lock

我之前对这个问题发表过评论("为什么java.lang.object不是抽象的?")说明我听说使用byte[0]作为锁比使用java.lang.Object更有效。我肯定我在某个地方读过这篇文章,但我想不起来在哪里:有人知道这是否是真的吗?

我怀疑这是由于byte[0]的实例化需要比Object稍微少一点的字节代码,尽管有人指出byte[0]需要额外的存储来存储长度字段,所以这听起来可能会抵消任何好处。


使用java.lang.instrument.instrumentation检查的范围:对象使用的是8个字节,16字节的字节[ 0 ]的需要。不幸的是,如果需要在字节大小,记录)。

我有时间来创建对象和一个字节[ 0 ](2次):对象是赢家。

所有的测试运行在2GHz的英特尔笔记本电脑,戴尔,windos XP)

使用clientVM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java version"1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode)

an implementation-specific approximation of the amount of storage
Object  = 8
byte[0] = 16

time to create 1000000000 instances
Object:  elapsed=11,140   cpu=9,766    user=9,703    [seconds]
byte[0]: elapsed=18,248   cpu=15,672   user=15,594   [seconds]

time to create 1000000000 instances
Object:  elapsed=11,135   cpu=9,828    user=9,750    [seconds]
byte[0]: elapsed=18,271   cpu=15,547   user=15,469   [seconds]

使用serverVM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java version"1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)

an implementation-specific approximation of the amount of storage
Object  = 8
byte[0] = 16

time to create 1000000000 instances
Object:  elapsed=8,441    cpu=7,156    user=7,125    [seconds]
byte[0]: elapsed=11,237   cpu=8,609    user=8,500    [seconds]

time to create 1000000000 instances
Object:  elapsed=8,501    cpu=7,234    user=7,156    [seconds]
byte[0]: elapsed=11,023   cpu=8,688    user=8,641    [seconds]

我想呆在new Object(),因为readability。:-)

代码演练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class ObjectArrayCompare {

  private static Object o;

  public static void main(String[] args) {
    Instrumentation instr = InstrumentationAgent.getInstrumentation();
    if (instr == null) {
        System.err.println("No Instrumentation, use "-javaagent:Instrumentation.jar"");
        return;
    }
    System.out.println();
    System.out.println("an implementation-specific approximation of the amount of storage");
    System.out.println("Object  =" + instr.getObjectSize(new Object()));
    System.out.println("byte[0] =" + instr.getObjectSize(new byte[0]));
    System.out.println();

    final int MAX = (int) 1.0e9;
    Timer timer;
    Times times;

    for (int j = 0; j < 2; j++) {
      System.out.println("time to create" + MAX +" instances");
      timer = new Timer();
      for (int i = 0; i < MAX; i++) {
        o = new Object();
      }
      times = timer.times();
      System.out.println("Object: " + times);

      timer = new Timer();
      for (int i = 0; i < MAX; i++) {
        o = new byte[0];
      }
      times = timer.times();
      System.out.println("byte[0]:" + times);

      System.out.println();
    }
  }
}

使用定时器* ThreadMXBean把《泰晤士报》。

定时器是一个I类*蛆的传送,它是Java的一个计时器。


我有足够的测试,它的奇妙。源代码:

1
2
3
4
5
6
7
8
9
public class Test {
    public static Object returnObject() {
        return new Object();
    }

    public static byte[] returnArray(){
        return new byte[0];
    }
}

字节码:

1
2
3
4
5
6
7
8
9
10
11
12
public static java.lang.Object returnObject();
  Code:
   0:   new     #2; //class java/lang/Object
   3:   dup
   4:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   7:   areturn

public static byte[] returnArray();
  Code:
   0:   iconst_0
   1:   newarray byte
   3:   areturn

那么你就在这样一个短代码的字节数组,数组有自己的创作,因为JVM的操作码。但那是什么意思?没有什么,真的。这是一个虚拟机,所以它绝对没有担保,少少的字节码指令的平均服务的实际物理CPU。当然,我们可以开始分析,但是不相当。如果有一个差分,在所有的,不管它的方式,它不有物。几乎是在当前对象的创建。你可能要开始使用你的long环指数之前,你甚至可以测量的总时间。


根据酒店Java语言规范,所有数组类型的类方法和类的对象,"I don’t知道字节[ 0 ]可以更高效的管理。

这似乎为第一版的规格为好:"父类被认为是在一个数组类型的对象。"


数组是使用更多的读者看来,国家工业。

不需要更多的对象是比创造更高效,因此如果它有足够的对象是创建,它很重要,你需要太多。


空的模式,使用Java中数组作为一个锁对象有小做与性能。

空数组(甚至new Object[0])是优选的,因为它们是可序列化的。用你给new Object()serialization自动启动。

我要用来做(不关心关于性能):

1
private final Object lock = new Object[0];

把这个数组创建原始字节码,new byte[0]也许会"更好"。

湖:是它好到做为一类瞬态锁序列化?


你mentions"效率"问题,但不说什么时候你良好的效率。答案是这样的远的对象的大小,但运行时间成本的内在关联和使用表示锁应是相同的。

所以你可以比较的开销使用的内在锁利用一java.util.concurrent.locks.ReentrantLock明确你自己atop AbstractQueuedSynchronizer或写。无论你能不能容忍把额外的参考一个单独分配的对象需要更多的细节-在你的问题来评估,但似乎你已经考虑到byte数组,你必须从你的内在锁使用不同的this参考。