• Synchronized 重量锁的数据结构以及Wait和notify的使用


    一、重量锁的数据结构
         1、 Synchronized升级到重量锁以后,会创建一个ObjectMonitor对象,对象中会有:当前持有锁的线程、WaitSet(保存处于Waiting状态的线程)、EntryList(保存处于Blocked状态的线程)
         2、重量锁本质:重量锁使用操作系统底层的 Mutex Lock
         3、ObjectMonitor作用:那在升级重量所过程中创建ObjectMonitor是用来对 资源竞争激烈的线程的进行统一管理的一种数据结构
         4、ObjectMonitor结构图:
          
    二、ObjectMonitor集合说明
       1 Blocked和Waiting状态的线程都处于阻塞状态,不占用CPU资源
       2 Blocked状态的线程会在锁被释放的时候唤醒
       3 Waiting状态的线程会在调用Notify或者NotifyAll时候唤醒,但唤醒后不会立即获得锁,仍然需要进入到EntrySet集合中竞争锁
     
    三、锁对象的Wait,线程做了什么?
        1 、持有锁的线程调用Wait,即可进入到WaitSet集合中
        2、调用Wait方法的锁一定是重量级锁(因为只有重量级锁才有ObjectMonitor,才有集合放置等待的对象)
        3、在“锁对象”(锁对象中含有ObjectMonitor的指针)上调用notify或者notifyAll,会到集合中唤醒相应的线程
     
        
    四、Wait和Sleep的区别
      相同:Wait和Sleep都可以使线程阻塞
      不同:
            1 Wait阻塞时候会释放锁,Sleep不会
            2 Wait通过notiry唤醒,Sleep时间到了自己会唤醒
            3 Wait是Object对象的方法,Sleep是Thread类的方法
            4 Wait需要配合Synchronized使用,否则会有异常,Sleep不需要
     
    五、Wait和Notify测试案例
       说明线程唤醒后还是需要获取锁才能执行
       
    package com.test.test1;
    
    
    import java.util.concurrent.atomic.AtomicBoolean;
    /**
    * 1 wait 和notify必须在synchroinzed中执行
    * 2 wait状态线程唤醒后,需要获取锁才能继续执行(本例字中t2唤醒t1后如果不释放锁,则t1是不会执行的)
    */
    public class Test6
    {
        public static void main( String[] args ) throws InterruptedException {
    
    
            Thread t1=null;
            Thread t2 = null;
    
    
            Object lock = new Object();
            AtomicBoolean haveMoney  = new AtomicBoolean(true) ;
    
    
            //第一个线程 t1 ,只要有钱,则花钱,直到没有钱了则退出
            t1 = new Thread(){
                @Override
                public void run() {
                    synchronized (lock){
                        while (haveMoney.get()){
                            try {
                                System.out.println("花钱");
                                lock.wait();
                                System.out.println("线程1 被换醒了 ");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("终于把所有钱花完了 ,哈哈。。。。。");
                    }
                }
            };
            //释放cpu资源,让t1 获取所并且wait
            Thread.sleep(1000);
            t2 = new Thread(()->{
                synchronized (lock){
                    // 唤醒锁 中等待的线程 t1
                    System.out.println("线程3去唤醒t2了");
                    lock.notifyAll();
                    //测试 T2不释放锁的情况下 t1不执行的情况
    //                try {
    //                    // t2 睡眠10s中,让t1获取到锁,则t1会自旋执行
    //                    Thread.sleep(10000);
    //                } catch (InterruptedException e) {
    //                    e.printStackTrace();
    //                }
    //
    //                //t2设置 t1标识为没钱,使t1循环结束,并唤醒t1
    //                System.out.println("设置线程t1状态为false=="+ haveMoney.get());
    //                haveMoney.set(false);
    //                lock.notifyAll();
    
    
                }
    
    
                try {
                    // t2 睡眠10s中,让t1获取到锁,则t1会自旋执行
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
    
                synchronized (lock){
                    //t2设置 t1标识为没钱,使t1循环结束,并唤醒t1
                    System.out.println("设置线程t1状态为false=="+ haveMoney.get());
                    haveMoney.set(false);
                    lock.notifyAll();
                }
            });
    
            t1.setName("线程t1 ");
            t2.setName("线程t3 ");
    
            t1.start();
            t2.start();
    
    
        }
    }
    View Code
     
     
  • 相关阅读:
    Translation Rule 和命中法则
    Cisco Extension Mobility配置步骤详解
    tclsh命令, cisco 快速测试工具
    136、多继承的优缺点,作为一个开发者怎么看待多继承
    135、 虚函数的内存结构,那菱形继承的虚函数内存结构呢
    134、隐式转换,如何消除隐式转换?
    133、说一下你理解的 ifdef endif代表着什么?
    132、 静态成员与普通成员的区别是什么?
    131、全局变量和static变量的区别
    130、定义和声明的区别
  • 原文地址:https://www.cnblogs.com/lean-blog/p/13719493.html
Copyright © 2020-2023  润新知