a351144b 2020-12-17 14:15 采纳率: 100%
浏览 16
已采纳

多线程唤醒的异常问题

问题是这样的,就是我建了3个线程t1,t2,t3,然后分别在t1线程唤醒t2线程,t2线程唤醒t3,
t1唤醒t2的时候用的锁是一个无关的对象,然后t2唤醒t3的时候用的锁对象是t1这个线程的对象

遇到的问题是:t1唤醒t2的时候把t3也唤醒了

疑问的点在于:1.notify只能唤醒一个线程,为什么两个线程都被唤醒了,2.notify是唤醒当前锁对象锁住的线程t2和t3使用不一样的锁,为什么同时被唤醒了,3.为什么如果使用无关对象(如用第25行的Object对象)作为锁依然可以正常的保证唤醒顺序

package com.yyc;

import lombok.Data;
import org.junit.jupiter.api.Test;

import java.util.Vector;

//import org.openjdk.jol.info.ClassLayout;

/**
 * @ClassName StudyThread
 * @Description: TODO
 * @Author huang.yuntao
 * @Date 2020/12/15
 * @Version V1.0
 **/
public class StudyThread {
    public static void main(String[] args) throws InterruptedException {
       new StudyThread().methodOne();
    }

    public void methodOne() throws InterruptedException {
        Vector<Cat> vector = new Vector();
        int size = 30;

        Object o = new Object();
        Thread ti = new Thread(()->{
            for (int i = 0; i < size; i++) {
                Cat cat = new Cat(i);
                vector.add(cat);
//                System.out.println(ClassLayout.parseInstance(cat).toPrintable());
                synchronized (cat){
//                    System.out.println(Thread.currentThread().getName()+"========="+i+"========="+ClassLayout.parseInstance(cat).toPrintable());
                }
            }
            synchronized (vector){
                vector.notify();
            }
        },"11111");
        ti.start();

        Thread t2 = new Thread(()->{
            synchronized (vector){
                try {
                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-------2");
                    vector.wait();
                    System.out.println("###################################-----2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < size; i++) {
                Cat cat = vector.get(i);
//                System.out.println(ClassLayout.parseInstance(cat).toPrintable());
                synchronized (cat){
//                    System.out.println(Thread.currentThread().getName()+"========="+i+"========="+ClassLayout.parseInstance(cat).toPrintable());
                }
            }
            synchronized (ti){
                ti.notify();
            }
        },"22222");
        t2.start();

        Thread t3 = new Thread(()->{
            synchronized (ti){
                try {
                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-------3");
                    ti.wait();
                    System.out.println("###################################-----3");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < size; i++) {
                Cat cat = vector.get(i);
//                System.out.println(ClassLayout.parseInstance(cat).toPrintable());
                synchronized (cat){
//                    System.out.println(Thread.currentThread().getName()+"========="+i+"========="+ClassLayout.parseInstance(cat).toPrintable());
                }
            }
        },"333");
        t3.start();
    }



    @Data
    private class Cat{
        public Cat(int id) {
            this.id = id;
        }

        private int id;
    }
}

  • 写回答

3条回答 默认 最新

  • boylilz 2020-12-17 15:39
    关注

    你线程t3等待的对象不对,换成

    vector或者重新定义一个对象,ti为线程对象
    1 线程对象的wait()方法运行后,可以不用其notify()方法退出,会在线程结束后,自动退出。
     2 线程间的等待唤醒机制,最好不要用线程对象做同步锁!
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置