a351144b
a351144b
2020-12-17 14:15
采纳率: 50%
浏览 6
已采纳

多线程唤醒的异常问题

问题是这样的,就是我建了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条回答 默认 最新

  • weixin_42031411
    boylilz 2020-12-17 15:39
    已采纳

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

    vector或者重新定义一个对象,ti为线程对象
    1 线程对象的wait()方法运行后,可以不用其notify()方法退出,会在线程结束后,自动退出。
     2 线程间的等待唤醒机制,最好不要用线程对象做同步锁!
    点赞 评论
  • weixin_42771946
    此时彼刻的蜗牛 2020-12-17 14:59

    大哥,你这线程通信demo太乱了,锁对象不能这样搞啊

    点赞 评论
  • a351144b
    a351144b 2020-12-23 15:00

    你们说的都对,但是没有解答我的问题,就是为什么不能用线程对象做同步锁

    点赞 评论

相关推荐