精华内容
下载资源
问答
  • 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是什么

    展开全文
  • 直接上code ... public class ...原因:output方法所属实例对象,然而static修饰的output3方法所属于字节码对象。两个方法不是所属同一个对象所以发生上述情况。 有兴趣可以看下这篇文章: 点击打开链接

    直接上code

    package cn.itcast.heima2;
    
    public class TraditionalThreadSynchronized {
    
    	public static void main(String[] args) {
    		new TraditionalThreadSynchronized().init();
    	}
    	
    	private void init(){
    		final Outputer outputer = new Outputer();
                     //线程1
    		new Thread(new Runnable(){
    			@Override
    			public void run() {
    				while(true){
    					try {
    						Thread.sleep(10);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					outputer.output("zhangxiaoxiang");
    				}
    				
    			}
    		}).start();
    		//线程2
    		new Thread(new Runnable(){
    			@Override
    			public void run() {
    				while(true){
    					try {
    						Thread.sleep(10);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					outputer.output3("lihuoming");
    				}
    				
    			}
    		}).start();
    		
    	}
            //内部类
    	static class Outputer{
    		
    		public void output(String name){
    			int len = name.length();
    			synchronized (Outputer.class)
    			{
    				for(int i=0;i<len;i++){
    					System.out.print(name.charAt(i));
    				}
    				System.out.println();
    			}
    		}
    		
    		//public synchronized void output2(String name){
    		//	int len = name.length();
    		//	for(int i=0;i<len;i++){
    		//			System.out.print(name.charAt(i));
    		//	}
    		//	System.out.println();
    		//}
    		
    		public static synchronized void output3(String name){
    			int len = name.length();
    			for(int i=0;i<len;i++){
    					System.out.print(name.charAt(i));
    			}
    			System.out.println();
    		}	
    	}
    }

    sysnchronized方法适用了类Java的内置锁,即锁住的方法所属对象本身。但这里有一个static修饰的方法,这里上面的红色字体修改为“this”的话,会发生以下情况:


    还没完全打印完成就被切了,,,未达到互斥的效果。

    原因是:output方法所属实例对象,然而static修饰的output3方法所属于字节码对象。两个方法不是所属同一个对象所以发生上述情况。

    有兴趣可以看下这篇文章:点击打开链接

    展开全文
  • 什么是管程? 管程保证了同一时刻只有一个进程/线程在管程内对共享变量进行操作,其封装了一套对共享资源访问的模型。其作用是保证多进程或者多线程访问同一个资源时,能够达到“互斥”、“同步”的效果。 管程的...

    什么是管程?

    管程保证了同一时刻只有一个进程/线程在管程内对共享变量进行操作,其封装了一套对共享资源访问的模型。其作用是保证多进程或者多线程访问同一个资源时,能够达到“互斥”、“同步”的效果。
    在这里插入图片描述
    管程的内部如上图所示。
    使用过程如下:

    1. 同步队列的线程去获取管程中共享变量的执行权,如果成功则执行对共享变量的处理。如果失败则返回同步队列。
    2. 对于成功获取到管程执行权的进行对共享变量的处理操作,执行完毕后可以唤醒同步队列的线程,重新竞争锁。也可以进行wait,将线程添加到等待队列中。当其他线程进行notify唤醒操作的时候,等待队列的线程移动到同步队列,重新竞争锁。

    管程的实现

    管程的实现,其实就是JAVA是通过sychronyzed关键字,和wait()、notify、notifyAll() 方法实现了整个管程模型。执行方式如下
    在这里插入图片描述

    总结

    1. java中synchronized关键字完整实现了管程的模型,因为synchronized锁的是对象,而wait()、notify()、notifyall()是对象的父类Object类中的方法。
    2. 管程在java的内部实现其实是一个monitor监视器,而monitor监视器中的字段(owner、recursions、waitSet、EntryList)就是实现管程的数据结构,只不是monitor将其封装在ObjectMonitor中。
    3. monitor实现的是最简单的,只有一个等待队列。而管程其实可以 设计多个等待队列。

    参考

    锁原理-管程
    java里的管程
    Monitor的实现原理

    展开全文
  • 转自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个循环。另外 如果针对某个锁  通过自旋 从来没有获得过, 现在以后获取这个锁将可能省略了自旋过程,以避免浪费处理器时间。有了适应性自旋 ,随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况就会越来越准确,虚拟机就会变得越来越聪明了。

    展开全文
  • Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这一个static方法,这意味着”某条线程”指的当前线程。 ...
  • 转自blog.csdn.net/mxiangjian/article/details/53115146 阅读本文,你可以了解到: 1、对象监视器锁(重量级锁)、轻量级锁...什么是对象监视器锁 为什么它叫重量级锁   我们知道在Java中实现同步的一种机制
  • Java - 锁和监视器什么区别?

    万次阅读 2019-08-19 16:49:31
    分享一个大牛的人工智能教程。...简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 锁(Lock) 逻辑上锁是对象内存堆中头部的一部分数据。JVM中的每个对象都有一个锁(或互斥锁),任何程序都可以使用...
  • 1.先了解什么是监视器 任意一个对象都拥有自己的监视器(monitor.enter–>monitor.exitd对应着获取锁和释放锁),当这个对象由同步块或者这个对象的同步方法调用时,执行方法的线程必须先获取到该对象的监视器...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。 简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 ...
  • Java并发中锁和监视器

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

    2014-12-08 14:44:06
    在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。  在Java中,可以使用synchronized关键字来标记一个方法或者代码块,当某个线程...
  • 在学习java线程同步的时候,总感觉同步监视器是多余的,因为既然已经用synchronize对代码块进行了锁定,那么传的参数还有什么意义? 首先,在语法上,该参数可为任意对象。 但是在实际项目中必须慎重选取同步监视器,...
  • 在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层如何工作的。 简短的答案,锁为实现监视器提供必要的支持。详细答案如下。 ...
  • 监视磁盘目录就用FileSystemWatcher 对象 “目录监视”这个词在我们身边并不少见,比如说FTP服务器中管理员需要对共享目录进行管理,查看用户都在做些什么操作。又如 黑客查看用户磁盘上的文件,都属于监视。...
  •  它内置与每一个Object对象中,相当于一个许可证。拿到许可证即可以进行操作,没有拿到则需要阻塞等待。    二:syncrhoized实现原理  syncrhoized又叫做内置锁,为什么呢?因为使用syncrhoized加锁的同步代....
  • 2. 线程在获取锁的时候,实际上就是获得一个监视器对象(monitor) ,monitor可以认为一个同步对象,所有的Java对象天生携带monitor。在hotspot源码的markOop.hpp文件中,可以看到下面这段代码。 多个线程访问...
  • 0007d5df4970 所以导致了死锁的出现 两个线程都有有一句: java.lang.Thread.State: BLOCKED (on object monitor) ...1、object monitor 任何一个对象都有的内置的数据结构,它用来协调使用当前对象的多个线程
  • 一切都是对象

    2021-03-10 21:07:07
    1.对象存储到什么地方 所有的Java对象都存放在堆中,堆一种...Java有一个“垃圾回收”,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其它新的对象使用。
  • 它内置与每一个Object对象中,相当于一个许可证。拿到许可证即可以进行操作,没有拿到则需要阻塞等待。 二:syncrhoized实现原理 syncrhoized又叫做内置锁,为什么呢?因为使用syncrhoized加锁的同步代码...
  • 属于对象或类的

    2008-02-25 17:04:00
    4、如果一个对象没有实例变量,或者一个类没有类变量,则和对象相关联的监视器,或者和类相关联的监视器什么都不监视。5、监视器是被某个对象或类所拥有的,而线程可以“获取对象的锁”(也就是获取了对
  • 理解synchronized对象

    2019-10-04 23:57:56
    在java虚拟机中,每个对象和类在逻辑上都和一个监视器相关联的。 对于对象来说,相关联的监视器保护对象的实例变量。 对于类来说,监视器保护类的类变量。 (如果一个对象没有实例变量,或者一个类没有变量...
  • 2.新的监视器对象 Codition 中的 await()方法 signal()方法代替了 Obj 中的方法 wait() notify方法 学习内容: ①什么是锁(lock)对象 监视器(Condition)对象 jdk 1.5版本后出现的代替同步锁的方法和代替Object中的...
  • Proxy 代理对象 如果想要监视某个对象中属性的读写,可以使用 ECMAScript2015 之前的 Object.defineProperty() 方法...如果你不能理解什么是代理的话,你可以把它想象成门卫。也就是说,无论你是从里面拿东西还是放东西
  • Java有个“垃圾回收”,用来监视用new创建的所有对象,并辨别哪些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。也就是说,你根本不必担心内存回收的问题。你只需要创建对象,一旦...
  • 监听器是专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视对象发生情况时立即采取相应的行动。Servlet监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序的...
  • 监听器是专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视对象发生情况时立即采取相应的行动。Servlet监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序的...

空空如也

空空如也

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

什么是监视器对象