Java中关于Integer++的问题

今天晚上在研究多线程相关问题的时候,写到如下程序
实现两个线程交替输出1 2 3 4 5 ······

public class ThreadTest {
    public static void main(String[] args) {
        Integer integer = new Integer(1);	// 共享对象integer
		// 共享对象传入两个线程中
        Thread t1 = new Thread(new MyThread1(integer));
        Thread t2 = new Thread(new MyThread2(integer));
		// 运行
        t1.start();
        t2.start();
    }
}

class MyThread1 implements Runnable {
    private Integer integer;
    // 通过构造方法传入共享对象
    MyThread1(Integer integer) {
        this.integer = integer;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (integer) {
                if (integer % 2 == 0) {		// 自动拆箱
                    try {
                        integer.wait();		// 偶数时线程1等待(同时释放锁)
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "->" + integer);
                integer++;
                integer.notifyAll();		// 唤醒integer上的两个线程
            }
        }
    }
}

class MyThread2 implements Runnable {
    private Integer integer;
    // 通过构造方法传入共享对象
    MyThread2(Integer integer) {
        this.integer = integer;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (integer) {
                if (integer % 2 == 1) {		// 自动拆箱
                    try {
                        integer.wait();		// 偶数时线程1等待(同时释放锁)
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "->" + integer);
                integer++;
                integer.notifyAll();		// 唤醒integer上的两个线程
            }
        }
    }
}

运行后报错信息如下:
Thread-0->1
Exception in thread “Thread-0” java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at MyThread1.run(MyTest.java:43)
at java.lang.Thread.run(Thread.java:748)

可见在Thread-0输出了第一条信息后发生Exception,notifyAll方法存在问题
在查阅相关资料后了解到
出现java.lang.IllegalMonitorStateException错误,由以下情况导致:

  1. 当前线程不含有当前对象的锁资源的时候,调用obj.wait()方法;

  2. 当前线程不含有当前对象的锁资源的时候,调用obj.notify()方法。

  3. 当前线程不含有当前对象的锁资源的时候,调用obj.notifyAll()方法。

因此可能出现了情况3的问题
而调用此方法的integer上的的确确是有两个线程的
因此,可能是由于integer++操作不当
故查阅Integer源码:

/**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

    /**
     * Constructs a newly allocated {@code Integer} object that
     * represents the specified {@code int} value.
     *
     * @param   value   the value to be represented by the
     *                  {@code Integer} object.
     */
    public Integer(int value) {
        this.value = value;
    }

Integer中的value字段被final修饰不可更改,所以integer++操作底层实际上会new一个新对象,value为integer的value值加1,再将integer引用指向这个新的对象,而新的对象是没有上锁的,故报错。

public class MyTest {
    public static void main(String[] args) {
        Integer integer = 0;
        System.out.println(System.identityHashCode(integer));	// 356573597
        integer++;
        //System.out.println(integer);	// 1
        System.out.println(System.identityHashCode(integer));	// 1735600054
    }
}

最后再由上述代码进一步证明,integer++前后内存地址是不同的。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值