synchronized 中Integer类型变量 使用wait notify报错

最近看到一个面试题,就随手写了多线程实现的多种方式,其中一直,一直报错

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;


public class Test {
  private static Integer flag = 0;
  public static void main(String[] args) throws InterruptedException {
        String[] string = {"a", "b", "c", "d"};
        String[] string2 = {"1", "2", "3", "4"};
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < string.length; i++) {
                synchronized (flag) {
                //代码段1
                    while (flag == 1) {
                        try {
                            flag.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(string[i]);
                    flag = 1;
                    flag.notifyAll();
                    
//					代码段2
//                    System.out.println(string[i]);
//之所以先notify,是因为使用wait当前线程就被挂起了,所以需要先唤醒另一个线程
//                    flag.notify();
//                    try {
//                        flag.wait();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                }
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < string2.length; i++) {
            //代码段1
                synchronized (flag) {
                    while (flag == 0) {
                        try {
                            flag.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(string2[i]);
                    flag = 0;
                    flag.notifyAll();
                    
//    				代码段2      
//                    System.out.println(string2[i]);
//                    flag.notify();
//                    try {
//                        flag.wait();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                }
            }
        });
        t1.start();
        //保证t1线程先执行
        Thread.sleep(1);
        t2.start();
       
    }
}

然后一直报错,报错信息如下:

a
1
Exception in thread "Thread-0" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
	at java.lang.Object.notifyAll(Native Method)
	at com.wxs.mengchen.test.Test.lambda$main$0(Test.java:33)
	at java.lang.Thread.run(Thread.java:748)
java.lang.IllegalMonitorStateException
	at java.lang.Object.notifyAll(Native Method)
	at com.wxs.mengchen.test.Test.lambda$main$1(Test.java:56)
	at java.lang.Thread.run(Thread.java:748)

看到这个错误,感觉很诧异,因为我已经使用synchronized修饰,以及使用的是获得锁的对象.wait以及notify方法的,后来,我发现Integer类是final类型的,每次重新赋值导致对象引用变了(synchronized底层我们知道锁的是对象头,对象都变了,那就是新的锁),所以再调用wait方法或者notify的时候,发现没拿到锁,没拿到锁怎么释放,所以报错,因此:其他基本类型的封装类型,如Short,Long,Double,String等,也不能作为同步对象.,有段时间没写多线程了,这块有点生疏了,实属不应该。
将代码段1注释掉,然后使用代码段2是正确实现方式之一,最后效果如下。

a
1
b
2
c
3
d
4

|本期文章就到这里了,我是梦辰,可以微信搜一搜「 梦辰的架构笔记 」公众号,保证是干货!!!欢迎大家和我交流。|
|----------------------------------------------------------|–|

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值