sleep()和wait()方法与对象锁、锁池、等待池

2023-10-29

一道Java的题目:

关于sleep()和wait(),以下描述错误的一项是: 
- A sleep是线程类(Thread)的方法,wait是Object类的方法; 
- B sleep不释放对象锁,wait放弃对象锁 
- C sleep暂停线程、但监控状态仍然保持,结束后会自动恢复 
- D wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态

1.关于对象锁

截取网上的一段话

所有对象都自动含有单一的锁。 
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。 
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。 
每当任务离开一个synchronized(同步)方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。

这段话令人感到迷惑,一个对象不是只有一个锁吗?只有获得这个对象的锁才能对它进行操作,若这个对象的锁被一个线程先获得,那就其他线程就需要等待。那多次加锁什么意思,锁不是依附于对象的吗? 
在往下的文章中,我暂且理解为一个对象有且只有一把锁,锁在不同线程间传递,一个线程可以多次获得同一个对象的锁。暂且不考虑一个对象上多个锁这种方法是不是确实存在,这对下面影响不大。

2.关于锁池和等待池

在Java中,每个对象都有两个池,锁(monitor)池和等待池

  • 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

  • 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.

深入理解: 
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。 
当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。 
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

注:wait() ,notifyAll(),notify() 三个方法都是Object类中的方法.

3.关于wait() ,notifyAll(),notify() 三个方法

  • wait() 
    public final void wait() throws InterruptedException,IllegalMonitorStateException

该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放锁。在从 wait()返回前,线程与其他线程竞争重新获得锁。如果调用 wait()时,没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException 的一个子类,因此,不需要 try-catch 结构。

  • notify() 
    public final native void notify() throws IllegalMonitorStateException

该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用 notify()时没有持有适当的锁,也会抛出 IllegalMonitorStateException。

该方法用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则线程规划器任意挑选出其中一个 wait()状态的线程来发出通知,并使它等待获取该对象的对象锁(notify 后,当前线程不会马上释放该对象锁,wait 所在的线程并不能马上获取该对象锁,要等到程序退出 synchronized 代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁),但不惊动其他同样在等待被该对象notify的线程们。当第一个获得了该对象锁的 wait 线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用 notify 语句,则即便该对象已经空闲,其他 wait 状态等待的线程由于没有得到该对象的通知,会继续阻塞在 wait 状态,直到这个对象发出一个 notify 或 notifyAll。这里需要注意:它们等待的是被 notify 或 notifyAll,而不是锁。这与下面的 notifyAll()方法执行后的情况不同。

  • notifyAll() 
    public final native void notifyAll() throws IllegalMonitorStateException

该方法与 notify ()方法的工作方式相同,重要的一点差异是:

notifyAll 使所有原来在该对象上 wait 的线程统统退出 wait 的状态(即全部被唤醒,不再等待 notify 或 notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll 线程退出调用了 notifyAll 的 synchronized 代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出 synchronized 代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

4.sleep()不会释放掉锁(监控) 
最开始的那道题答案是D

 

 

https://blog.csdn.net/u014561933/article/details/58639411

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sleep()和wait()方法与对象锁、锁池、等待池 的相关文章

随机推荐

  • qt ×掉子窗口后,进程还没有停止的问题

    掉子窗口后 子窗口还在接受数据的问题 当子窗口显示时 先关闭父窗口 调用的先后顺序为 当子窗口显示时 先关闭子窗口 调用的先后顺序为 找到原因 此时子窗口的析构函数没有执行 解决方案 先说解决方案 给子窗口设置以下属性 setAttribu
  • UE4 去掉自动曝光(光线自适应)

    UE4在没有PostprocessingVolumn时 会在场景中加入自动曝光 有时会导致过亮或者过暗 解决方法 关闭ProjectSetting Rendering DefaultSetting中的AutoExposure 自动曝光 在场
  • CentOS安装错误:no default or ui configuration

    靠 以后再也不用浏览器自带的下载工具下载镜像文件了 原来是下载的不完整 但是显示完全下载完毕了 真特么误导人 文件的checksum不对 references https www centos org forums viewtopic ph
  • c++11 pod类型(了解)

    c 11 pod类型 了解 啥是POD类型 POD全称Plain Old Data 通俗的讲 一个类或结构体通过二进制拷贝后还能保持其数据不变 那么它就是一个POD类型 平凡的定义 1 有平凡的构造函数 2 有平凡的拷贝构造函数 3 有平凡
  • ReactHook EffectHook

    副作用操作 使得函数组件能够进行生命周期的操作 可以有多个 类组件中相同的生命周期会进行覆盖 会在 可以看作是以下生命周期函数的结合 componentDidMount componentDidUpdate 和 componentWillU
  • MR应用开发 —— Hadoop权威指南10

    1 Configuration Hadoop的配置API 之前 在获取Hadoop文件实例时 经常会创建一个Configuration实例 Configuration是Hadoop用于配置的API 是property和value的集合 ad
  • centos系统elasticseach安装

    Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎 一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎 当然 Elasticsearch 并不仅仅是 Lucene 那么简单 它不仅包括了全文搜索功能 还可以
  • Python堆积条形图、双轴图、多子图、圆圈热力图示例

    准备工作 使用Python绘图首先需要导入需要的库 并确保中文和负号的正常显示 import os import xlrd import pandas as pd import numpy as np import matplotlib p
  • 了解在Linux系统下不同Shell介绍以及切换

    了解在Linux系统下不同Shell介绍以及切换 引言 在Linux系统中 Shell是用户与操作系统内核之间的接口 它是一个命令行解释器 用于执行用户输入的命令并与操作系统进行交互 在Linux中 常见的Shell包括zsh bash f
  • 用js实现二分查找法

    二分查找法 二分查找也称折半查找 Binary Search 它是一种效率较高的查找方法 但是 折半查找要求线性表必须采用顺序存储结构 而且表中元素按关键字有序排列 function binarySearch arr target let
  • Leetcode错题本1-实现一个 atoi 函数,使其能将字符串转换成整数。

    题目描述 请你来实现一个 atoi 函数 使其能将字符串转换成整数 首先 该函数会根据需要丢弃无用的开头空格字符 直到寻找到第一个非空格的字符为止 接下来的转化规则如下 如果第一个非空字符为正或者负号时 则将该符号与之后面尽可能多的连续数字
  • 【已解决】微信小程序调用方法说找不到 undefined

    问题 在另一个方法里面调用方法报错 说方法找不到 那大多数人都会意识到是this指针的问题 但是我明明加了es6语法 应该可以获取到this的啊 整个世界都迷幻了 桥豆麻袋 找到问题了 this指针的操作要在函数一开始就操作 很明显我下面调
  • 2023年最常见中高级Android面试题全解析,看完碾压面试官!!!

    最近正值秋招 一直在给公司招聘Android程序员 我从 2015 年做 TeamLeader 开始就习惯性的收集平时遇到的 Android技术问题或周围朋友见过的面试题 经过不断筛选 终于凝练成一套实用的小题库 题库中所有的问题请看下文
  • 抽象方法与抽象类 --笔记

    抽象方法 只有方法名 参数表和返回值 没有方法体 既然抽象方法没有方法体 那么也就不能被执行 如果某个类含有抽象方法 那么这个类必须定义为抽象类 即在类定义前用关键字abstract修饰 但需要注意 一个抽象类可以没有抽象方法 抽象类没有具
  • 数据密集型应用系统设计(1)

    文章目录 可靠 可拓展可维护的应用系统 软件系统最重要的三个特征 可靠性 可扩展性 可维护性 小结 可靠 可拓展可维护的应用系统 软件系统最重要的三个特征 可靠性 即使发生了某些错误 系统也可继续正常工作 故障 faults 或者叫错误 与
  • 正则表达式的验证

    java正则表达式通过java util regex包下的Pattern类与Matcher类实现 建议在阅读本文时 打开java API文档 当介绍到哪个方法时 查看java API中的方法说明 效果会更佳 Pattern类用于创建一个正则
  • 关于gd32f103的adc的一点说法

    最近使用gd32替换了stm32 但是在移植adc程序的时候出现了一些问题 这里进行一下总结 是给自己一个提醒 同时也是给后来人一点点参考 gd32f103是与stm32管脚一一对应的一款国产单片机 在性能上更为优越 价格上更加便宜 但是在
  • 数据结构Java实现01----算法概述

    本文转载至 http www cnblogs com smyhvae p 4724692 html 一 数据结构涵盖的内容 二 算法的基本概念 1 算法的概念 Algorithm 是对特定问题求解步骤的一种描述 它是指令的有限序列 其中每一
  • 最优隐神经元数目 算法 matlab,请问Matlab如何用遗传算法优化神经网络隐含层神经元个数...

    close all clear all clc global p global t global nvar global ncase global s1 global s2 global cl disp 开始运行基于LM正则优化的GABP神
  • sleep()和wait()方法与对象锁、锁池、等待池

    一道Java的题目 关于sleep 和wait 以下描述错误的一项是 A sleep是线程类 Thread 的方法 wait是Object类的方法 B sleep不释放对象锁 wait放弃对象锁 C sleep暂停线程 但监控状态仍然保持