精华内容
下载资源
问答
  • 多线程-Java中的对象监视器是什么意思? 为什么要使用这个词?在阅读有关Java线程的文章时,我经常注意到这样的表达:“当前线程是该对象的监视器的所有者”。 我的意思是:线程有权在对象上进行操作。 但是我很困惑...

    多线程-Java中的对象监视器是什么意思? 为什么要使用这个词?

    在阅读有关Java线程的文章时,我经常注意到这样的表达:“当前线程是该对象的监视器的所有者”。 我的意思是:线程有权在对象上进行操作。 但是我很困惑,为什么我们使用“对象的监视器”而不是“对象的锁”?

    简而言之,我不知道“监控”一词的含义这个问题可能很奇怪而且很简单。 但我希望任何人都能帮助解决它。3KS

    6个解决方案

    44 votes

    但是我很困惑,为什么要使用“对象的监视器”一词而不是“对象的锁”?

    请参阅ulmangt的答案以获取在此上下文中解释“监视”一词的链接。

    为什么使用术语“监视”而不是“锁定”? 严格来说,这些术语的含义确实有所不同……尤其是如果您以最初打算使用的方式使用它们。

    “锁”是指具有获取和释放原语的东西,这些原语和原语保持某些锁属性。 例如 专用或单作者/多读者。

    “监视程序”是一种机制,可确保在任何给定时间只有一个线程可以执行给定的代码段。 可以使用锁(和“条件变量”,允许线程等待或通知满足条件的其他线程)来实现此功能,但它不仅仅是锁。 实际上,在Java情况下,不能直接访问监视器使用的实际锁。 (您不能说“ Object.lock()”来阻止其他线程获取它,就像使用Java Lock实例一样。)

    简而言之,如果要学究的话,“ monitor”实际上是比“ lock”更好的术语,用于描述Java提供的特性。 但是实际上,这两个术语几乎可以互换使用。

    Stephen C answered 2019-09-24T08:12:08Z

    20 votes

    监视器只是一个对象的术语,其方法可以在多线程环境中安全使用。

    在Monitors上有一篇很棒的Wikipedia文章:

    [http://en.wikipedia.org/wiki/Monitor_(synchronization)]

    如果向下滚动,甚至还会有专门关于Java的部分。

    ulmangt answered 2019-09-24T08:12:54Z

    5 votes

    它的监视器是object周围的synchronized块,它控制对象上的锁定。 这是一个例子

    synchronized (object) {

    while ()

    object.wait(timeout);

    ... // Perform action appropriate to condition

    }

    abbas answered 2019-09-24T08:13:20Z

    4 votes

    尽管现在回答这个问题已经很晚了,但我还是想补充一下,以防万一。

    这是未同步的Java方法中的Java代码的同步块

    public void add(int value){

    synchronized(this){

    this.count += value;

    }

    }

    在示例“ this”中,使用了add方法。同步实例方法将其所属的对象用作监视对象。

    =>在同一监视对象上同步的Java代码块内只能执行一个线程。

    aman answered 2019-09-24T08:14:13Z

    2 votes

    Java虚拟机使用监视器来支持多线程。 监视器通过两个概念实现这一点-运行线程时互斥(这里是“锁定”的地方)和作为线程间通信手段的协调(这里是对象的wait和notify方法的地方)。

    从“ Inside JVM”中阅读以下部分将清除这个疑问,在这里是否很好解释(第20章,线程同步)-

    [https://www.artima.com/insidejvm/ed2/threadsynchP.html]

    adityalad answered 2019-09-24T08:14:53Z

    2 votes

    从Java虚拟机内部引用

    Java虚拟机中的线程在到达时请求锁定   在监视区域的开头。 在Java中,有两种   监视区域:同步语句和同步方法。

    监控

    监视器就像一栋建筑物,其中包含一个可以   一次只能被一个线程占用。 房间通常包含   一些数据。 从线程进入这个房间的时间到它进入的时间   离开后,它可以独占访问房间中的任何数据。 进入   监视程序的建立称为“进入监视程序”。 进入   建筑物内的特殊房间称为“获取显示器”。   占领房间称为“拥有显示器”,然后离开房间   房间被称为“释放显示器”。 离开整个建筑是   称为“退出监视器”。

    监视器除了与少量数据相关联之外,   与一个或多个代码位相关联,在本书中   称为监视区域。

    如前所述,该语言提供了两种内置方法   识别程序中的监视区域:同步语句和   同步方法。 这两种机制,实现了相互   Java虚拟机支持同步的排除方面   机器的指令集。

    为了实现监视器的互斥功能,Java   虚拟机将锁(有时称为互斥锁)与每个   对象和类。 锁就像特权,只有一个线程可以   随时“拥有”。

    允许单个线程多次锁定同一对象。 对于   每个对象,Java虚拟机都会维护一个数量的计数   对象被锁定的次数。 解锁对象的数量为   零。 当线程首次获取锁时,计数为   再次增加到一。 每次线程获得对   同一对象,计数再次增加。

    Zane XY answered 2019-09-24T08:16:16Z

    展开全文
  • 转自blog.csdn.net/mxiangjian/article/details/53115146 阅读本文,你可以了解到: 1、对象监视器锁(重量级锁)、...什么是对象监视器锁 为什么它叫重量级锁   我们知道在Java中实现同步的一种机制 利用sync...

    转自blog.csdn.net/mxiangjian/article/details/53115146

    阅读本文,你可以了解到:

    1、对象监视器锁(重量级锁)、轻量级锁、偏向锁的含义

    2、它们之间的区别

    3、每一种锁的使用场景什么。

     

    我们跟着一下几个问题一步一步深入了解:

    什么是对象监视器锁 为什么它叫重量级锁 

         我们知道在Java中实现同步的一种机制 是利用synchronized关键字来修饰同步代码块,它的本质就是对象进行加锁在达到同步的目的 我们称这种锁为对象监视器锁。

    那么为什么使用这个关键字来修饰代码块,就能让线程达到互斥同步的目的呢?

           根据java虚拟机规范,被synchronized关键字修饰的代码块在被编译成字节码的时候 会在该代码块开始和结束的时候插入monitorenter 和 moniterexist指令,虚拟机在执行这两个指令的时候会检查对象的锁状态是否为空或当前线程是否已经拥有该对象锁 如果是 则将对象锁的计数器加1 直接进入同步代码执行。如果不是当前线程就要阻塞等待 等到锁释放 。

    那么为什么说这种操作很重呢?

           java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统的帮忙,这就要从用户态转换到核心态,因此状态转换需要花费很多的处理器时间,对于代码简单的同步块(如被synchronized修饰的get 或set方法)状态转换消耗的时间有可能比用户代码执行的时间还要长,所以说synchronized是java语言中一个重量级的操纵。所以jvm的研究人员在1.6的时候花费了大量的时间来优化重量级锁,于是在1.6中出现了轻量级锁,偏向锁,锁消除,适应性自旋锁,锁粗化(自旋锁在1.4就有 只不过默认的是关闭的,jdk1.6是默认开启的),这些操作都是为了在线程之间更高效的共享数据 ,解决竞争问题。

    那么轻量级锁的原理是什么呢 它为什么要比synchronized要轻呢

         轻量级锁 是在jdk1.6之中加入的 它名字中的“轻量级”是相对不使用系统互斥量来实现的传统锁而言的,首先需要强调的是它不是用来代替重量级锁的,它的本意是在没有多线程竞争的情况下 减少使用操作系统互斥量产生的性能消耗。
       要理解轻量级锁,必须从HotSpot虚拟机的对象头的内存布局来介绍,HotSpot虚拟机的对象头由两部分组成,第一部分是存储对象自身运行时的数据 如哈希码 GC分代年龄,锁标记位等 官方称为Mark Word 它是实现轻量级锁和偏向锁的关键,另外一部分用于存储指向方法区对象类型数据的指针,如果是数组对象的话 还会有一个额外的部分用于
    存储数组长度,以32位虚拟机为例  对象头的描述如下图所示:

     

    锁状态

    25 bit

    4bit

    1bit

    2bit

    23bit

    2bit

    是否是偏向锁

    锁标志位

    轻量级锁

    指向栈中锁记录的指针

    00

    重量级锁

    指向互斥量(重量级锁)的指针

    10

    GC标记

    11

    偏向锁

    线程ID

    Epoch

    对象分代年龄

    1

    01

    无锁

    对象的hashCode

    对象分代年龄

    0

    01

     

    根据上图可知 32位虚拟机用2bit表示锁标记  00表示轻量级锁 01表示无锁状态(还有一个bit为表示 有无偏向锁) 10表示重量级锁。
          简单的了解了对象在内存中的布局后,我们把话题返回到轻量级锁的执行过程,在代码进入同步块的时候,如果同步对象没有被锁定,虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储对象目前Mark Word的拷贝,这时候线程堆栈与对象头的状态如图所示:

     

     

    然后虚拟机将使用CAS操作尝试将对象头中的Mark Word 更新为指向当前线程Lock Record的指针,如果这个更新执行成功了,那么这个线程就拥有了这个对象的锁,并且将Mard Word中的标记位改为00,即表示该对象处于轻量级锁状态,这时候线程堆和对象头的状态如图所示:

    如果这个状态更新失败了,虚拟机将会检查对象中的Mark Word 是否指向当前线程的栈帧,如果是直接进入同步代码块 执行,如果不是 说明有线程竞争。如果有两条以上的线程在抢占资源,那轻量级锁就不再有效,要膨胀为重量级锁,锁的状态更改为10, Mard Word中存储的就是指向重量级锁的指针 后面等待的锁就要进入阻塞状态。

           上述描述的轻量级锁的加锁过程,它的解锁过程也是通过CAS来进行操作的,如果Mard Word仍然指向当前线程的锁记录,那就要用CAS操作把当前的Mard Word和线程中复制的Lock Record 替换回来,如果替换成功 那么真个同步过程就完成了 ,如果替换失败,说明有其他线程尝试过获取该锁,那就要释放锁的同时 唤醒被挂起的线程。

           轻量级锁性能提升的依据是 “对于绝大多数的锁”在整个同步周期被都是不存在竞争的,这是一个经验数据,如果没有竞争 轻量级锁使用CAS操作避免使用系统互斥量的开销。但如果存在竞争。除了互斥的开销外 还要额外的发生CAS操作因此在有竞争的情况下 轻量级锁会比传统的重量级锁还要慢
         总结一下 :轻量级锁的 “轻” 在于当没有多线程竞争的情况下 只利用简单的CAS 操作 来代替 操作系统互斥量在减少开销 所以要轻。但是如果存在多线程竞争的情况是 轻量级锁不但不会轻  反而会更重。

    那什么是偏向锁呢

        以上介绍了轻量级锁,理解了轻量级锁那么在理解偏向锁就会更容易了,我们首先回顾一下 轻量级锁的引入是 是为了提升在没有线程竞争的情况下 执行同步代码的效率的。那么还有一种特殊的情况就是,始终只有一个线程在执行同步块,在这种情况下 即使使用轻量级锁 也是需要多个CAS操作的,所以也有一部分开销,于是JVM研究人员又引入了另一种锁 即偏向锁 来适用这种情况。偏向锁中的偏 就是偏心的“偏” 它的意思是让这个锁始终偏向第一个获取它的线程,如果接下来的执行过车个中 ,该锁没有被其他线程获取 则持有偏向锁的线程将永远不需要再进行同步。当开启了偏向锁功能,当代码进入同步块的时候,虚拟机会检查当前线程是否处于无锁状态01 且标记位为0 没有偏向锁 ,那么线程就会使用CAS操作吧获取到这个锁的线程ID记录在对象的Mark Word中,如果获取成功 ,那么持有偏向锁的线程以后在每次进入这个锁相关的同步块的时候,虚拟机不再使用任何的同步操作只坚持对象头中是否是当前线程ID,如果是直接进入  省去了CAS操作。当另外一个线程获取该对象锁的时候,偏向模式就会宣告结束,根据锁对象的当前状态,撤销偏向后恢复大无锁状态或偏向锁状态,之后的操作就如同上述轻量级锁的介绍。

        总结一下  偏向锁只适用于在只有一个线程执行同步代码块的情况 ,如果程序中大部分锁总是被不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下有时候禁用偏向锁反而可以提高性能。

    以上介绍了 三个比较男理解的锁 以及他们之间的转换 下面介绍下 锁粗话  锁消除 适应性自旋锁的概念

    锁粗化:

             原则上,在我们编写代码的时候,我们总是推荐将同步代码块的范围尽量缩小,只有在数据争用的时候才进行同步,这样是为了使得需要同步的操作数量尽可能的变小,如果存在锁竞争,那等待的线程也能很快拿到锁。
    大部分情况下 ,上面的原则是正确的,但是如果一些列连续的操作都需要对一个对象反复的加锁和解锁,甚至加锁操作时出现在循环里面的,这样即使没有线程竞争,频繁的加锁也会导致不必要的性能消耗例如代码:
    StringBuffer sb = new StringBuffer();
    sb.append(1);
    sb.append(2);
    sb.append(3);
    .......
    如果出现这样的情况,虚拟机会探索出这样一串零碎的操作都对同一个对象进行加锁,虚拟机就会将加锁同步的范围扩展(粗化)到整个序列的开始和结束,以上述代码为例,就是将锁范围扩展到第一个append之前 到最后一个append之后。这样只需要一次加锁就可以了。

    锁消除:
             锁消除是指虚拟机在即时编译器在运行时,对于一些在代码上要求同步,但是被检测到不可能存在数据竞争的锁进行消除。


    自旋锁和适应性自旋锁:
            前面我在讨论互斥同步的时候,提到了互斥同步操作对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转移到内核态去执行,这些操作给系统的并发性能带来了很大的压力,同时虚拟机团队也注意到在很多应用上,共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得,如果物理机器上有
    一个以上的处理器,能让两个以上的线程同时并行执行,我们就可以让后面请求的那个线程先“稍等一会”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁,为了让线程不放弃处理器的时间,我们只需要让下城执行一个忙循环(自旋) 这项技术就是自旋锁。在jdk1.6中 自旋锁是默认开启的  自旋不能代替最,因为自旋本身也要一直占用处理器时间,如果锁被占用的时间很短,那么自旋等待的效果就会很好,反之,如果
    锁被占用的时间很长,那么自旋的线程只能白白的占用处理器自旋,而不会做任何有用的工作,反而会给性能带来浪费。因此 自旋等待的时间就要有一定的限度如果超过了这个限度仍然没有获取锁,那么就要里用传统的方式将线程挂起。在jdk1.5 这个限度是一定的写死的在1.6之后 虚拟机研究人员引入了适应性自旋锁,适应性自旋锁意味着 自旋的时间不在是固定的了,而是由前一次在同一个锁上的自旋时间以及锁的拥有者的状态
    来决定,如果在同一个锁对象上,自旋锁刚刚成功获得过锁,并且持有锁的线程正在运行,那么虚拟机就会认为这次自旋也很有可能再次成功,进而他会将自旋等待的时间相对持续的更长,比如100个循环。另外 如果针对某个锁  通过自旋 从来没有获得过, 现在以后获取这个锁将可能省略了自旋过程,以避免浪费处理器时间。有了适应性自旋 ,随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况就会越来越准确,虚拟机就会变得越来越聪明了。

    展开全文
  • Monitor监视器对象

    2021-03-15 17:45:24
    在分析完对象头以后,我们知道对象头里其实有一个重量级锁的指针,而重量级锁的指针指向的就是monitor监视器对象。 synchronized无论修饰代码块还是修饰普通方法和静态方法,本质上还都作用在对象上 为什么说...

    在分析完对象头以后,我们知道对象头里其实是有一个重量级锁的指针,而重量级锁的指针指向的就是monitor监视器对象。
    synchronized无论是修饰代码块还是修饰普通方法和静态方法本质上还都是作用在对象上

    为什么说本质上synchronized还是作用在对象上(猜测)?

    synchronized分为对象锁和类锁。对象锁,锁的是实例化对象。而类锁加在了类上,会对每一个该类的实例化对象上锁,说白了还是加在对象上。
    类的信息是存放在方法区,该类的每一个实例对象都有一个Kclass point指针(对象头中)指向其类信息。如果类有了锁标志,其实例化对象中的markword的锁标志会修改,从而所有的实例化对象的会拥有相同的锁,也就是拥有相同的monitor。所以本质还是作用在对象上。

    • 不管是类锁还是对象锁,多线程获取锁的本质其实是获取的monitor对象。

    monitor对象长啥样?

    monitor
    当多个线程同时访问一段同步代码时,首先会进入_EntryList队列中,当某个线程获取到对象的monitor后进入_Owner区域并把monitor中的_owner变量设置为当前线程,同时monitor中的计数器_count加1。即获得对象锁。

    若持有monitor的线程调用wait()方法,将释放当前持有的monitor,_owner变量恢复为null,_count自减1,同时该线程进入_WaitSet集合中等待被唤醒。
    在这里插入图片描述

    参考
    Monitor原理
    monitor是什么

    展开全文
  • 转自blog.csdn.net/mxiangjian/article/details/53115146 阅读本文,你可以了解到: 1、对象监视器锁(重量级锁)、轻量级锁...什么是对象监视器锁 为什么它叫重量级锁   我们知道在Java中实现同步的一种机制

    转自blog.csdn.net/mxiangjian/article/details/53115146


    阅读本文,你可以了解到:

    1、对象监视器锁(重量级锁)、轻量级锁、偏向锁的含义

    2、它们之间的区别

    3、每一种锁的使用场景什么。


    我们跟着一下几个问题一步一步深入了解:

    什么是对象监视器锁 为什么它叫重量级锁 

         我们知道在Java中实现同步的一种机制 是利用synchronized关键字来修饰同步代码块,它的本质就是对象进行加锁在达到同步的目的 我们称这种锁为对象监视器锁。

    那么为什么使用这个关键字来修饰代码块,就能让线程达到互斥同步的目的呢?

           根据java虚拟机规范,被synchronized关键字修饰的代码块在被编译成字节码的时候 会在该代码块开始和结束的时候插入monitorenter 和 moniterexist指令,虚拟机在执行这两个指令的时候会检查对象的锁状态是否为空或当前线程是否已经拥有该对象锁 如果是 则将对象锁的计数器加1 直接进入同步代码执行。如果不是当前线程就要阻塞等待 等到锁释放 。

    那么为什么说这种操作很重呢?

           java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统的帮忙,这就要从用户态转换到核心态,因此状态转换需要花费很多的处理器时间,对于代码简单的同步块(如被synchronized修饰的get 或set方法)状态转换消耗的时间有可能比用户代码执行的时间还要长,所以说synchronized是java语言中一个重量级的操纵。所以jvm的研究人员在1.6的时候花费了大量的时间来优化重量级锁,于是在1.6中出现了轻量级锁,偏向锁,锁消除,适应性自旋锁,锁粗化(自旋锁在1.4就有 只不过默认的是关闭的,jdk1.6是默认开启的),这些操作都是为了在线程之间更高效的共享数据 ,解决竞争问题。

    那么轻量级锁的原理是什么呢 它为什么要比synchronized要轻呢

         轻量级锁 是在jdk1.6之中加入的 它名字中的“轻量级”是相对不使用系统互斥量来实现的传统锁而言的,首先需要强调的是它不是用来代替重量级锁的,它的本意是在没有多线程竞争的情况下 减少使用操作系统互斥量产生的性能消耗。
       要理解轻量级锁,必须从HotSpot虚拟机的对象头的内存布局来介绍,HotSpot虚拟机的对象头由两部分组成,第一部分是存储对象自身运行时的数据 如哈希码 GC分代年龄,锁标记位等 官方称为Mark Word 它是实现轻量级锁和偏向锁的关键,另外一部分用于存储指向方法区对象类型数据的指针,如果是数组对象的话 还会有一个额外的部分用于
    存储数组长度,以32位虚拟机为例  对象头的描述如下图所示:

    锁状态

    25 bit

    4bit

    1bit

    2bit

    23bit

    2bit

    是否是偏向锁

    锁标志位

    轻量级锁

    指向栈中锁记录的指针

    00

    重量级锁

    指向互斥量(重量级锁)的指针

    10

    GC标记

    11

    偏向锁

    线程ID

    Epoch

    对象分代年龄

    1

    01

    无锁

    对象的hashCode

    对象分代年龄

    0

    01


    根据上图可知 32位虚拟机用2bit表示锁标记  00表示轻量级锁 01表示无锁状态(还有一个bit为表示 有无偏向锁) 10表示重量级锁。
          简单的了解了对象在内存中的布局后,我们把话题返回到轻量级锁的执行过程,在代码进入同步块的时候,如果同步对象没有被锁定,虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储对象目前Mark Word的拷贝,这时候线程堆栈与对象头的状态如图所示:



    然后虚拟机将使用CAS操作尝试将对象头中的Mark Word 更新为指向当前线程Lock Record的指针,如果这个更新执行成功了,那么这个线程就拥有了这个对象的锁,并且将Mard Word中的标记位改为00,即表示该对象处于轻量级锁状态,这时候线程堆和对象头的状态如图所示:


    如果这个状态更新失败了,虚拟机将会检查对象中的Mark Word 是否指向当前线程的栈帧,如果是直接进入同步代码块 执行,如果不是 说明有线程竞争。如果有两条以上的线程在抢占资源,那轻量级锁就不再有效,要膨胀为重量级锁,锁的状态更改为10, Mard Word中存储的就是指向重量级锁的指针 后面等待的锁就要进入阻塞状态。

           上述描述的轻量级锁的加锁过程,它的解锁过程也是通过CAS来进行操作的,如果Mard Word仍然指向当前线程的锁记录,那就要用CAS操作把当前的Mard Word和线程中复制的Lock Record 替换回来,如果替换成功 那么真个同步过程就完成了 ,如果替换失败,说明有其他线程尝试过获取该锁,那就要释放锁的同时 唤醒被挂起的线程。

           轻量级锁性能提升的依据是 “对于绝大多数的锁”在整个同步周期被都是不存在竞争的,这是一个经验数据,如果没有竞争 轻量级锁使用CAS操作避免使用系统互斥量的开销。但如果存在竞争。除了互斥的开销外 还要额外的发生CAS操作因此在有竞争的情况下 轻量级锁会比传统的重量级锁还要慢
         总结一下 :轻量级锁的 “轻” 在于当没有多线程竞争的情况下 只利用简单的CAS 操作 来代替 操作系统互斥量在减少开销 所以要轻。但是如果存在多线程竞争的情况是 轻量级锁不但不会轻  反而会更重。

    那什么是偏向锁呢

        以上介绍了轻量级锁,理解了轻量级锁那么在理解偏向锁就会更容易了,我们首先回顾一下 轻量级锁的引入是 是为了提升在没有线程竞争的情况下 执行同步代码的效率的。那么还有一种特殊的情况就是,始终只有一个线程在执行同步块,在这种情况下 即使使用轻量级锁 也是需要多个CAS操作的,所以也有一部分开销,于是JVM研究人员又引入了另一种锁 即偏向锁 来适用这种情况。偏向锁中的偏 就是偏心的“偏” 它的意思是让这个锁始终偏向第一个获取它的线程,如果接下来的执行过车个中 ,该锁没有被其他线程获取 则持有偏向锁的线程将永远不需要再进行同步。当开启了偏向锁功能,当代码进入同步块的时候,虚拟机会检查当前线程是否处于无锁状态01 且标记位为0 没有偏向锁 ,那么线程就会使用CAS操作吧获取到这个锁的线程ID记录在对象的Mark Word中,如果获取成功 ,那么持有偏向锁的线程以后在每次进入这个锁相关的同步块的时候,虚拟机不再使用任何的同步操作只坚持对象头中是否是当前线程ID,如果是直接进入  省去了CAS操作。当另外一个线程获取该对象锁的时候,偏向模式就会宣告结束,根据锁对象的当前状态,撤销偏向后恢复大无锁状态或偏向锁状态,之后的操作就如同上述轻量级锁的介绍。

        总结一下  偏向锁只适用于在只有一个线程执行同步代码块的情况 ,如果程序中大部分锁总是被不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下有时候禁用偏向锁反而可以提高性能。

    以上介绍了 三个比较男理解的锁 以及他们之间的转换 下面介绍下 锁粗话  锁消除 适应性自旋锁的概念

    锁粗化

             原则上,在我们编写代码的时候,我们总是推荐将同步代码块的范围尽量缩小,只有在数据争用的时候才进行同步,这样是为了使得需要同步的操作数量尽可能的变小,如果存在锁竞争,那等待的线程也能很快拿到锁。
    大部分情况下 ,上面的原则是正确的,但是如果一些列连续的操作都需要对一个对象反复的加锁和解锁,甚至加锁操作时出现在循环里面的,这样即使没有线程竞争,频繁的加锁也会导致不必要的性能消耗例如代码:
    StringBuffer sb = new StringBuffer();
    sb.append(1);
    sb.append(2);
    sb.append(3);
    .......
    如果出现这样的情况,虚拟机会探索出这样一串零碎的操作都对同一个对象进行加锁,虚拟机就会将加锁同步的范围扩展(粗化)到整个序列的开始和结束,以上述代码为例,就是将锁范围扩展到第一个append之前 到最后一个append之后。这样只需要一次加锁就可以了。

    锁消除:
             锁消除是指虚拟机在即时编译器在运行时,对于一些在代码上要求同步,但是被检测到不可能存在数据竞争的锁进行消除。


    自旋锁和适应性自旋锁:
            前面我在讨论互斥同步的时候,提到了互斥同步操作对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转移到内核态去执行,这些操作给系统的并发性能带来了很大的压力,同时虚拟机团队也注意到在很多应用上,共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得,如果物理机器上有
    一个以上的处理器,能让两个以上的线程同时并行执行,我们就可以让后面请求的那个线程先“稍等一会”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁,为了让线程不放弃处理器的时间,我们只需要让下城执行一个忙循环(自旋) 这项技术就是自旋锁。在jdk1.6中 自旋锁是默认开启的  自旋不能代替最,因为自旋本身也要一直占用处理器时间,如果锁被占用的时间很短,那么自旋等待的效果就会很好,反之,如果
    锁被占用的时间很长,那么自旋的线程只能白白的占用处理器自旋,而不会做任何有用的工作,反而会给性能带来浪费。因此 自旋等待的时间就要有一定的限度如果超过了这个限度仍然没有获取锁,那么就要里用传统的方式将线程挂起。在jdk1.5 这个限度是一定的写死的在1.6之后 虚拟机研究人员引入了适应性自旋锁,适应性自旋锁意味着 自旋的时间不在是固定的了,而是由前一次在同一个锁上的自旋时间以及锁的拥有者的状态
    来决定,如果在同一个锁对象上,自旋锁刚刚成功获得过锁,并且持有锁的线程正在运行,那么虚拟机就会认为这次自旋也很有可能再次成功,进而他会将自旋等待的时间相对持续的更长,比如100个循环。另外 如果针对某个锁  通过自旋 从来没有获得过, 现在以后获取这个锁将可能省略了自旋过程,以避免浪费处理器时间。有了适应性自旋 ,随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况就会越来越准确,虚拟机就会变得越来越聪明了。

    展开全文
  • Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这一个static方法,这意味着”某条线程”指的当前线程。 ...
  • 直接上code ... public class ...原因:output方法所属实例对象,然而static修饰的output3方法所属于字节码对象。两个方法不是所属同一个对象所以发生上述情况。 有兴趣可以看下这篇文章: 点击打开链接
  • Java - 锁和监视器什么区别?

    万次阅读 2019-08-19 16:49:31
    分享一个大牛的人工智能教程。...简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 锁(Lock) 逻辑上锁是对象内存堆中头部的一部分数据。JVM中的每个对象都有一个锁(或互斥锁),任何程序都可以使用...
  • 我正在开发Android,我无法弄清楚为什么我的一些线程会进入“监视”状态.我读过它可能因为“同步”问题,但我不确定对象如何不释放它们的锁.任何人都可以帮助如何调试这个或你看到我做错了什么?这同步对象没有被...
  • mutex实际上就是对象本身 } 复制代码什么是监视器模式 java的监视器模式,将对象所有可变状态都封装起来,并由对象自己的内置锁来保护,即一种实例封闭。 比如hashtable就是运用的监视器模式。 它的get操作就是用的...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别?嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。简短的答案,锁为实现监视器提供必要的支持。详细答案如下。锁(lock)...
  • 什么是管程? 管程保证了同一时刻只有一个进程/线程在管程内对共享变量进行操作,其封装了一套对共享资源访问的模型。其作用保证多进程或者多线程访问同一个资源时,能够达到“互斥”、“同步”的效果。 管程的...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别?嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。简短的答案,锁为实现监视器提供必要的支持。详细答案如下。锁(lock)...
  • 对象头区域,里面会有一个锁的字段,其实很简单,就是锁的模式是什么:偏向锁,轻量锁,重量锁,还有锁指向的指针当一个线程,将锁的指针通过CAS指向自己的栈帧,就说明获得了锁监视器是什么?监视器只是实现同步...
  • 1.先了解什么是监视器 任意一个对象都拥有自己的监视器(monitor.enter–>monitor.exitd对应着获取锁和释放锁),当这个对象由同步块或者这个对象的同步方法调用时,执行方法的线程必须先获取到该对象监视器...
  • 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个...
  • Java并发中锁和监视器

    2018-10-11 11:59:28
    在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。 简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 ...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。 简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 锁...
  • 监视器(Monitor)内部,如何做线程同步的?程序应该做哪种级别的同步? 参考答案 监视器和锁在Java虚拟机中一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个...
  • 什么是对象

    2014-12-08 14:44:06
    在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。  在Java中,可以使用synchronized关键字来标记一个方法或者代码块,当某个线程...
  • 在学习java线程同步的时候,总感觉同步监视器是多余的,因为既然已经用synchronize对代码块进行了锁定,那么传的参数还有什么意义? 首先,在语法上,该参数可为任意对象。 但是在实际项目中必须慎重选取同步监视器,...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。 简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 ...
  • servlet(二)、监听器 javax.servlet.Filter一、什么是监听器javaWeb规范包括三个技术点:servlet 、listener 、...在javaWeb中监听器是用来监听三个对象(request、session、servletConfig)的状态。监听器的相关概...
  • 监视磁盘目录就用FileSystemWatcher 对象 “目录监视”这个词在我们身边并不少见,比如说FTP服务器中管理员需要对共享目录进行管理,查看用户都在做些什么操作。又如 黑客查看用户磁盘上的文件,都属于监视。...
  •  它内置与每一个Object对象中,相当于一个许可证。拿到许可证即可以进行操作,没有拿到则需要阻塞等待。    二:syncrhoized实现原理  syncrhoized又叫做内置锁,为什么呢?因为使用syncrhoized加锁的同步代....
  • 一:MonitorMonitor一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量。...因为使用syncrhoized加锁的同步代码块在字节码引擎中执行时,其实通过锁对象的monitor的取用与释放...
  • 一:MonitorMonitor一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量。...因为使用syncrhoized加锁的同步代码块在字节码引擎中执行时,其实通过锁对象的monitor的取用与释放...
  • 0007d5df4970 所以导致了死锁的出现 两个线程都有有一句: java.lang.Thread.State: BLOCKED (on object monitor) ...1、object monitor 任何一个对象都有的内置的数据结构,它用来协调使用当前对象的多个线程
  • 1. 首先,Java中的每个对象都派生自Object类,而每个Java Object在JVM内部都有一个native的C++对象oop/oopDesc进行...多个线程访问同步代码块时,相当于去争抢对象监视器修改对象中的锁标识,上面的代码中ObjectMonit...
  • 自己在网上找到了想要的答案:jvm不会把已经申请的内存还给OS, 因为很可能马上又要分配给新的对象,每次向 OS 申请内存很慢的。所以管理控制台显示的内存使用情况和windows任务管理中的不一样。jvm中有两个参数 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 467
精华内容 186
关键字:

对象监视器是什么