详解java 对象锁与类锁

一.什么是对象锁

对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞,
例如:

public class MyObject {
  private synchronized void method1(){
    try {
      System.out.println(Thread.currentThread().getName());
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  //synchronized修饰为同步方法,如果先调用method1,则4秒后才会调用method2
  //如果不用synchronized修饰,则可以直接异步调用,没有影响
  private void method2(){
    System.out.println(Thread.currentThread().getName());
  }
}

创建一个类,synchronized修饰普通方法,即为对象锁,那么这个时候,多个线程访问同一个对象实例的这个方法时,是会同步的,并且只有一个线程执行完,另一个线程才会执行:

public static void main(String[] args) {
    //创建一个对象
    MyObject myObject=new MyObject();

    Thread t1=new Thread (new Runnable() {
      @Override
      public void run() {
        myObject.method1();
      }
    },"t1");
    Thread t2=new Thread (new Runnable() {
      @Override
      public void run() {
        myObject.method1();
      }
    },"t2");
    t1.start();
    t2.start();
}

即,打印t14秒之后,t2才会打印,因为两个线程调用的是同一个对象实例的方法,即同一把锁,所有会同步执行
而如果是不同对象实例的话,则没有影响,因为两个线程调用的是不同实例的锁方法,即不是同一把锁,没有关系,所以会正常输出,不会同步

public static void main(String[] args) {
    //创建两个对象
    MyObject myObject=new MyObject();
    MyObject myObject01=new MyObject();

    Thread t1=new Thread (new Runnable() {
      @Override
      public void run() {
        myObject.method1();
      }
    },"t1");
    Thread t2=new Thread (new Runnable() {
      @Override
      public void run() {
        myObject01.method1();
      }
    },"t2");
    t1.start();
    t2.start();
  }

二 对象锁的几种形式以及应用案例

1 synchronized修饰普通方法属于对象锁,

2 synchronized修饰的代码块传入this也属于对象锁

应用:减小锁粒度,第二种形式就比较好,比如A线程调用一个同步方法需要很长时间,那么B就要等待很长时间,这个时候可以将必须同步的代码使用synchronized代码块, 不需要同步的先执行,节约资源

三 类锁

类锁是锁住整个类,当有多个线程来声明这个类的对象时候将会被阻塞,直到拥有这个类锁的对象呗销毁或者主动释放了类锁,这个时候在被阻塞的线程被挑选出一个占有该类锁,声明该类的对象。其他线程继续被阻塞住

(上面百度的),即一句话,不管多少个对象,多少个对象,共用一把多,且只有一把,不管怎么调用,都会同步

上面方法加static变类锁:

private static synchronized void method1(){
    try {
      System.out.println(Thread.currentThread().getName());
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  这个时候无论线程调用的是多少个对象实例的方法,都会同步

四 类锁形式

synchronized修饰静态方法属于类锁

以上就是详解java 对象锁与类锁的详细内容,更多关于java对象锁与类锁的资料请关注我们其它相关文章!

(0)

相关推荐

  • 透彻理解Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别

    本文讲述了Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别.分享给大家供大家参考,具体如下: Synchronized和Static Synchronized区别 通过分析这两个用法的分析,我们可以理解java中锁的概念.一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁).实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是

  • Java类锁、对象锁、私有锁冲突测试

    类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class)的代码段,如下文中的increament(): 2.对象锁:在代码中的方法上加了synchronized的锁,或者synchronized(this)的代码段,如下文中的synOnMethod()和synInMethod():

  • 详解java 对象锁与类锁

    一.什么是对象锁 对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞, 例如: public class MyObject { private synchronized void method1(){ try { System.out.println(Thread.currentThread().getName());

  • 详解Java对象的内存布局

    前言 今天来讲些抽象的东西 -- 对象头,因为我在学习的过程中发现很多地方都关联到了对象头的知识点,例如JDK中的 synchronized锁优化 和 JVM 中对象年龄升级等等.要深入理解这些知识的原理,了解对象头的概念很有必要,而且可以为后面分享 synchronized 原理和 JVM 知识的时候做准备. 对象内存构成 Java 中通过 new 关键字创建一个类的实例对象,对象存于内存的堆中并给其分配一个内存地址,那么是否想过如下这些问题: 这个实例对象是以怎样的形态存在内存中的? 一个O

  • 详解Java 中的嵌套类与内部类

    详解Java 中的嵌套类与内部类 在Java中,可以在一个类内部定义另一个类,这种类称为嵌套类(nested class).嵌套类有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类较少使用,非静态嵌套类使用较多,也就是常说的内部类.其中内部类又分为三种类型: 1.在外部类中直接定义的内部类. 2.在函数中定义的内部类. 3.匿名内部类. 对于这几种类型的访问规则, 示例程序如下: package lxg; //定义外部类 public class OuterClass { //外部类静态成员变量

  • 详解java JDK 动态代理类分析(java.lang.reflect.Proxy)

    详解java JDK 动态代理类分析(java.lang.reflect.Proxy) /** * JDK 动态代理类分析(java.lang.reflect.Proxy使用) * * @author 张明学 * */ public class ProxyStudy { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 动态代理类:通用指定类加载器,和接

  • 详解JAVA 时间处理相关类

    时间处理相关类: 1.java.util.Date:时间类 2.java.text.DateFormat:时间格式化类(抽象类),实现类:java.text.SimpleDateFormat 3.java.util.Calendar:日历类(抽象类),实现类:java.util.GergorianCalendar 1.java.util.Date 时间就是一个数轴,在计算机中,1970年1月1日00:00:00定位基准时间,也就是数轴的原点,每个度量单位是毫秒(1000毫秒=1秒) java中我

  • 详解Java中的日期类

    Java 编程语言中时间的处理类有 Date类与 Calendar类.目前官方不推荐使用 Date类,因为其不利于国际化:而是推荐使用 Calendar类,并使用 DateFormat 类做格式化处理. 一.Date 类介绍 Date 表示特定的瞬间,精确到毫秒. 在 JDK 1.1 之前,类 Date 有两个其他的函数.它允许把日期解释为年.月.日.小时.分钟和秒值.它也允许格式化和解析日期字符串. 不过,这些函数的 API 不易于实现国际化.从 JDK 1.1 开始,应该使用 Calenda

  • 详解Java对象序列化为什么要使用SerialversionUID

    1.首先谈谈为什么要序列化对象 - 把对象转换为字节序列的过程称为对象的序列化. - 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器

  • 详解Java对象创建的过程及内存布局

    一.对象的内存布局 对象头 对象头主要保存对象自身的运行时数据和用于指定该对象属于哪个类的类型指针. 实例数据 保存对象的有效数据,例如对象的字段信息,其中包括从父类继承下来的. 对齐填充 对齐填充不是必须存在的,没有特别的含义,只起到一个占位符的作用. 二.对象的创建过程 实例化一个类的对象的过程是一个典型的递归过程. 在准备实例化一个类的对象前,首先准备实例化该类的父类,如果该类的父类还有父类,那么准备实例化该类的父类的父类,依次递归直到递归到Object类. 此时,首先实例化Object类

  • 详解Java抽象类与普通类的区别

    浅谈抽象类 在面向对象概念中,所有的对象都是通过类来描述的,但是反过来,并不是所有的类都是用来描述对象的.如果一个类中没有足够多的信息来描述一个具体的对象,这样的类就是抽象类. 看到这里可能还是觉得有些难以理解,举个例子说明一下:说到动物你会想到什么?猫,狗,鸡鸭鹅?当然这些都可以.那么动物这两个字,你能确定一个具体的对象吗?显然不能.甚至更严格意义上讲,说到猫你会想到什么?橘猫,短美- 毕竟: 一千个人心中有一千个哈姆雷喵. 所以我们在设计中,动物类可以设计成为抽象类,而某一种特定的物种可以采

  • 详解Java的构造方法及类的初始化

    目录 一. 利用构造方法给对象初始化 1. 构造方法的概念 2. 构造方法的特性 3. 子类构造方法 4. 避免在构造方法中调用重写的方法 二. 对象的默认初始化 三. 就地初始化对象 四. 类的初始化顺序 1. 普通类(没有继承关系) 2. 派生类( 有继承关系) 一. 利用构造方法给对象初始化 1. 构造方法的概念 构造方法(也称为构造器)是一个特殊的成员方法,其名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次. 构造方法的作用就是给对象中的成员进行初

随机推荐