1. 为什么单线程操作不是连续的,这是因为虽然你使用了 synchronized (obj) {} 来尝试获取排它锁,但是其他线程把obj修改了,比如从1修改到2 ,又因为Integer使用了享元模式,1 和 2 不是同一个对象,所以你的每个线程可能锁的不是同一个对象,所以也就无法按照你的需求输出,将obj修改为final常量后,各个线程锁定的肯定是同一个对象了,也就可看到连续输出了。
2. 第二个问题不太熟悉,直接使用 javap -c synTest.class 查看字节码如下,因为 synchronized 进入监视器的字节码指令是 monitorenter ,退出监视器的字节码命令是monitorexit,而这两个命令仅仅出现一次分别是第6行指令和106行指令,所以并没有同步消除优化
public void add();
Code:
0: aload_0
1: getfield #3 // Field obj:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter
7: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
10: invokestatic #16 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
13: invokevirtual #17 // Method java/lang/Thread.getName:()Ljava/lang/String;
16: invokevirtual #18 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
19: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
22: new #19 // class java/lang/StringBuilder
25: dup
26: invokespecial #20 // Method java/lang/StringBuilder."<init>":()V
29: invokestatic #16 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
32: invokevirtual #17 // Method java/lang/Thread.getName:()Ljava/lang/String;
35: invokevirtual #21 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: ldc #22 // String ===
40: invokevirtual #21 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #3 // Field obj:Ljava/lang/Object;
47: invokevirtual #23 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
50: invokevirtual #24 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: invokevirtual #18 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
56: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
59: new #19 // class java/lang/StringBuilder
62: dup
63: invokespecial #20 // Method java/lang/StringBuilder."<init>":()V
66: invokestatic #16 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
69: invokevirtual #17 // Method java/lang/Thread.getName:()Ljava/lang/String;
72: invokevirtual #21 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
75: ldc #25 // String -
77: invokevirtual #21 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
80: aload_0
81: getfield #3 // Field obj:Ljava/lang/Object;
84: invokevirtual #23 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
87: invokevirtual #24 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
90: invokevirtual #18 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
93: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
96: invokestatic #16 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
99: invokevirtual #17 // Method java/lang/Thread.getName:()Ljava/lang/String;
102: invokevirtual #18 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
105: aload_1
106: monitorexit
107: goto 115
110: astore_2
111: aload_1
112: monitorexit
113: aload_2
更多Java并发编程的学习笔记欢迎访问 https://www.zhoutao123.com/page/book/11