java并发,操作i++,一个诡异的问题!

源代码

[code="java"]
public class Test {

public static void main(String[] args) {

    final TestRun run = new TestRun();

    Thread thread = new Thread(run);
    Thread thread2 = new Thread(run);
    thread.start();
    thread2.start();

}

}

class TestRun implements Runnable {

public Integer i    = 0;
public Object  lock = new Object();

@Override
public void run() {
    synchronized (i) {
        i++;
        System.out.println("step1:" + i);
        i++;
        System.out.println("step2:" + i);
    }
}

}

[/code]
运行的结果。按理说,锁住了i对象,同步快中的内容顺序执行,结果为:
step1:1
step2:2
step1:3
step2:4

但结果却是:
step1:1
step1:2
step2:3
step2:4
或者
step1:1
step2:3
step1:2
step2:4

貌似没有锁住。
当改为synchronized (lock){
……
}
结果就正常了!

为什么????锁住对象了,不能对对象进行操作吗?

原因是Java的自动封箱和解箱操作在作怪。
这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。
其它基本类型的封装类,如Short、Long等等也不能作为同步对象

加锁失败。

小哀同学 已经道出天机。通过反编译代码来看这个问题。
[code="java"]// Decompiled by DJ v2.9.9.60 Copyright 2000 Atanas Neshkov Date: 2012-4-5 13:09:35
// Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version!
// Decompiler options: packimports(3)
// Source File Name: Airplane.java

package test;

import java.io.PrintStream;

class TestRun
implements Runnable
{

TestRun()
{
    i = Integer.valueOf(0);
    lock = new Object();
}

public void run()
{
    synchronized(i)
    {
        i = Integer.valueOf(i.intValue() + 1);
        System.out.println((new StringBuilder("step1:")).append(i).toString());
        i = Integer.valueOf(i.intValue() + 1);
        System.out.println((new StringBuilder("step2:")).append(i).toString());
    }
}

public Integer i;
public Object lock;

}[/code]

[code="java"]i = Integer.valueOf(i.intValue() + 1);
[/code]
在这里i已经变为新的对象。所以当线程2进入时临界区的对象i为新的没有加锁的对。
所以线程2能够闯入。加锁失败。在这里这种加锁方法本身就是不好的。直接用lock就行了。你可以[code="java"]Integer ii = new Integer (0);
synchronized(i)
[/code]
像上面那样也是没有问题的。
你遇到的这种现象属于“临界区资源泄漏”。