zoukankan      html  css  js  c++  java
  • java 对象锁学习

    机制

      锁机制是用来解决多线程共享资源时产生的冲突问题的。java 为每一个对象关联一个对象锁,通常把锁分为对象锁和类锁,他们的本质都是对象锁,只不过对象锁关联的是类的 Object 对象 (java.lang.Object),而类锁关联的是类的 Class 对象 java.lang.Class。
      jvm 对每个锁都有一个计数

    • 若该计数为 0,则锁没有被占用,可以被访问它的线程来持有
    • 一个对象的对象锁已被某个线程持有,新的线程来访问时将被挂起,知道持有它的线程释放该锁并且计数为 0
    • 一个线程已经持有了某个对象的锁,该线程再次访问该对象锁时可以重入,且计数 +1
    • 一个线程释放对象锁时,该锁的计数 -1,当某个锁的计数为 0 时锁被释放,可以被线程竞争

    分类

    • 不管怎么分类,java 中通过 synchronized 来实现的锁其本质都是对象锁
    • java 内部同步机制实现通常有两种方式,synchronized 修饰方法和语句块
    • synchronized 关键字作用于对象,这个对象可以是类的实例对象,也可以是 Class 对象

      • 类锁

      1 public class SyncObject {
      2     // 类锁1:通过static方法加同步锁
      3     public static synchronized void syncMethod1() {
      4         try {
      5             System.out.println("testMethod1 start!");
      6             Thread.sleep(3000);
      7         } catch (InterruptedException e) {
      8             e.printStackTrace();
      9         }
     10         System.out.println("testMethod1 end!");
     11     }
     12 
     13     public void syncMethod2() {
     14         // 类锁2:通过同步语句块传递Class类型参数
     15         synchronized (SyncObject.class) {
     16             try {
     17                 System.out.println("testMethod2 start!");
     18                 Thread.sleep(3000);
     19             } catch (InterruptedException e) {
     20                 e.printStackTrace();
     21             } finally {
     22                 System.out.println("testMethod2 end!");
     23             }
     24         }
     25     }
     26 }

    类锁作用于类的 Class 对象,对一个类来说,无论该类有多少个实例,它的静态变量和静态方法都只有一份,保存在 Class 对象中。通过对 Class 对象加锁来实现的同步语句或同步方法,无论该对象的哪个实例来访问,都需要竞争这个类锁

    •    对象锁

      1 public class SyncObject {
      2     // 对象锁1(方法锁):通过方法加同步锁
      3     public synchronized void syncMethod1() {
      4         try {
      5             System.out.println("testMethod1 start!");
      6             Thread.sleep(3000);
      7         } catch (InterruptedException e) {
      8             e.printStackTrace();
      9         }
     10         System.out.println("testMethod1 end!");
     11     }
     12 
     13     public void syncMethod2() {
     14         // 对象锁2:通过同步语句块传递Object类型参数
     15         synchronized (this) {
     16         // 此处的参数可以是本实例this,也可以是其它实例比如new SyncObject(),传入哪个实例就对哪个实例加锁
     17             try {
     18                 System.out.println("testMethod2 start!");
     19                 Thread.sleep(3000);
     20             } catch (InterruptedException e) {
     21                 e.printStackTrace();
     22             } finally {
     23                 System.out.println("testMethod2 end!");
     24             }
     25         }
     26     }
     27 }


    对象锁会对类的实例对象加锁,每一个 new 操作都会获得一个新的实例对象,对于 synchronized 修饰的非 static 方法或传递参数为实例对象的语句块,各个实例对象会拥有自己的锁。

    TIPS

      • synchronized 的作用范围是对象

        • synchronized 修饰的代码块需要传入一个对象参数(这个对象可以使 Class 对象),这个对象参数就是它的作用范围
        • synchronized 修饰的非静态方法的作用范围是 this,即当前对象实例。修饰静态方法时作用范围是这个类,即 Class 对象
      • synchronized 的粒度针不可再分


        因为锁是针对整个对象的,所以当某个对象的锁被持有后,其它线程不能持有该锁
        • 当一个线程调用某个对象 a 的 synchronized 方法(a.syncMethod1)在该方法结束之前,该对象的其它 synchronized 方法 (a.syncMethod2..) 都将不能被调用。同步代码块 synchronized(a)与 a.syncMethod1 有同样的作用周期
        • 当一个线程调用某个类 A 的 static synchronized 方法(A.staticSyncMethod1)在该方法结束前,该类的其它 static synchronized 方法(A.staticSyncMethod2..)都将不能被调用
        • 当一个线程调用某个对象 a 的 synchronized 方法(a.syncMethod1)在该方法结束之前,该类的其它 static synchronized 方法 (A.syncMethod2..) 还可以被调用,反之也成立
        • synchronized 的只对它修饰的模块加锁

          • 未被 synchronized 修饰的模块是可以被异步访问的, 因为线程访问它的时候并不需要获取对象锁
      • 相关阅读:
        团队作业 总结
        个人作业 Alpha项目测试
        第二次作业
        交互式多媒体图书平台的设计与实现
        基于VS Code的C++语言的构建调试环境搭建指南
        码农的自我修养之必备技能 学习笔记
        工程化编程实战callback接口学习
        如何测评一个软件工程师的计算机网络知识水平和编程能力
        深入理解TCP协议及其源代码
        Socket与系统调用深度分析
      • 原文地址:https://www.cnblogs.com/ios9/p/7473165.html
      Copyright © 2011-2022 走看看