彩虹海呐- 2021-03-19 11:57 采纳率: 100%
浏览 47
已采纳

java多线程锁的对象不能改变其值吗

一个很简单的生产者消费者模型,但是搞不懂为什么报错了。

锁的对象是LOCK时,可以正常跑,当我把锁的对象改为count本身的时候,就报错了。

报错信息:


当前数量: 0 ,消费者等待...
当前数量: 1 ,生产者生产完毕!
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at TestProducterCunsumer$Producter.run(TestProducterCunsumer.java:61)
    at java.lang.Thread.run(Thread.java:748)
 

代码:

/**
 * ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
 * &  | |      | |   * *     * *   | |      | |  &
 * &  | |      | |    * *   * *    | |      | |  &
 * &  | -------- |     * * * *     | -------- |  &
 * &  | -------- |      *   *      | -------- |  &
 * &  | |      | |     * * * *     | |      | |  &
 * &  | |      | |    * *   * *    | |      | |  &
 * &  | |      | |  * *       * *  | |      | |  &
 * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 */

/**
 * Created by HXH on 2021/3/18
 *
 * @desc
 */
public class TestProducterCunsumer {
    //锁count报错
    public static Integer count = 0;
    //锁LOCK 正常
    private static String LOCK = "lock";

    public static void main(String[] args) {
        TestProducterCunsumer testProducterCunsumer = new TestProducterCunsumer();
//        Producter producter = testProducterCunsumer.new Producter();
//        Cunsumer cunsumer = testProducterCunsumer.new Cunsumer();
        Producter producter = new Producter();
        Cunsumer cunsumer = new Cunsumer();
        Thread producterThread = new Thread(producter);
        Thread cunsumerThread = new Thread(cunsumer);
        producterThread.start();
        cunsumerThread.start();
    }

    //生产者
    static class Producter implements Runnable {
        @Override
        public void run() {

            while (true) {

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (count) {

                    if (count > 0) {
                        try {
                            System.out.println("当前数量: " + count + " ,生产者等待...");
                            count.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }

                    count++;
                    System.out.println("当前数量: " + count + " ,生产者生产完毕!");
                    count.notifyAll();
                    System.out.println("已通知消费者来消费!");

                }
            }

        }
    }

    //   消费者
    static class Cunsumer implements Runnable {

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (count) {

                while (true) {
                    if (count <= 0) {
                        System.out.println("当前数量: " + count + " ,消费者等待...");
                        try {
                            count.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.println("当前数量: " + count + " ,消费者消费!");
                    count--;
                    count.notifyAll();
                    System.out.println("已通知生产者来生产!");
                }
            }

        }
    }
}
  • 写回答

2条回答 默认 最新

  • 规则边缘 2021-03-19 17:47
    关注

    1、synchronized 简单点理解就是查询及修改一个对象实例的对象头中的标志位,两个线程要锁同一个对象才能实现同步。

    2、生产者执行count++后,count变量实际上指向了另外一个对象,然而生产者线程并不持有新对象的锁,所以会在执行count.notifyAll时报IllegalMonitorStateException。

    3、使用synchronized (count.toString().intern())报错原理也是一样,生产者执行count++后,count.toString().intern()或count实际上也会指向另外一个对象。所以会在执行count.toString().intern().notifyAll或count.notifyAll时报IllegalMonitorStateException。

    4、如果先定义 private static String cintern = count.toString().intern(); 再锁cintern 对象就行可以。就是因为生产者执行count++后,cintern变量并不会改变,当前线程持有cintern指向的对象的锁,执行cintern.notifyAll自然不会报错。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题