Charles Yan 2020-05-26 18:56 采纳率: 0%
浏览 101

第二个线程是什么时候获取到demo.list对象锁的,进入等待的

  • 问题描述

    按理说,当第一个线程(前面)的synchronized获得对象锁了以后,第二个线程(后面)就只能等待,当第一个线程添加完list,执行demo.list.notify()方法只会通知等待队列中的第一个相关线程,根据输出结果看是去唤醒第二个线程,这个时候第二个线程执行添加list。问题是:但是notify()方法不会释放锁,且第一个线程先获取到锁,那么第二个线程是应该是无法先获取到锁的,是如何进入wait()方法,等待第一个线程获取的

  • 案例代码

    
        public class ThreadCommunication {
    
                private final List<Integer> list =new ArrayList<>();
    
                public static void main(String[] args) {
                    ThreadCommunication demo =new ThreadCommunication();
    
                    new Thread(()->{
                        for (int i=0;i<10;i++){
                            synchronized (demo.list){
                                if(demo.list.size()%2==1){
                                    try {
                                        demo.list.wait();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                demo.list.add(i);
                                System.out.print(Thread.currentThread().getName());
                                System.out.println(demo.list);
                                demo.list.notify();//不会释放锁
                            }
                        }
    
                    }).start();
    
                    new Thread(()->{
                        for (int i=0;i<10;i++){
                            synchronized (demo.list){
                                if(demo.list.size()%2==0){
                                    try {
                                        demo.list.wait();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                demo.list.add(i);
                                System.out.print(Thread.currentThread().getName());
                                System.out.println(demo.list);
                                demo.list.notify();
                            }
                        }
                    }).start();
                }
    
        }
    
  • 写回答

1条回答 默认 最新

  • qybao 2020-05-27 13:58
    关注

    假设第一个线程先抢到锁执行,因为不会满足if(demo.list.size()%2==1)的,所以不会wait,就会执行demo.list.add(i)。离开了synchrnized(demo.list){}的作用域(也就是花括号)锁就会自动释释放,demo.list.notify();是唤醒wait的线程抢锁的,所以此时线程1和线程2都有机会再抢锁。假如还是线程1先抢到锁,那线程1就会满足if(demo.list.size()%2==1)而wait,让出锁来让线程2执行;假如是线程2抢到锁,线程2因为不满足if(demo.list.size()%2==0)而继续添件元素demo.list.add(i),然后调用demo.list.notify唤醒线程1一起抢锁(_被唤醒的线程是从wait以后的代码继续执行的,所以不会重新判断if条件,所以此时就算if条件不满足,线程也继续执行后面的代码_)。。。依次反复执行,直到每个线程的for循环结束

    你把if(demo.list.size()%2==1)改成while(demo.list.size()%2==1)能解决上面的不重新判断if的问题,同样线程2的if(demo.list.size()%2==0)也要改成while

    评论

报告相同问题?

悬赏问题

  • ¥50 随机森林与房贷信用风险模型
  • ¥50 buildozer打包kivy app失败
  • ¥30 在vs2022里运行python代码
  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备