zoukankan      html  css  js  c++  java
  • 对象级别锁 vs 类级别锁(Java)

    前言

    对于多线程(并发)和Spring Boot这两块在同步进行学习中,在看到使用synchronized关键字使操作同步时,看到和C#中不一样的东西,所以这里呢,就深入学习了下,若有错误之处,还望指正。

    对象级别锁 vs 类级别锁

    我们知道由于并发会导致线程不安全的问题,此时我们手段之一采取线程同步,也就是说使得所有并发线程在执行中保持同步的过程,当方法声明为同步时,传递到同步块中的对象称之为监视器或锁定对象,如果有另外一个线程也在执行该同步方法,那么该线程将被阻塞,直到线程释放该监视器或锁定对象。我们在类中已定义的方法或块上使用synchronized关键字,同时synchronized关键字不能与类定义中的变量或属性一起使用。

    对象级别锁

    所谓的对象级别锁,也就是针对非静态方法执行同步块锁定,那么同步块中的监视器或锁定对象则是基于对象实例,有如下三种形式

    class Test {
        public synchronized void LockMethod() {
        }
    }

    或者

    class Test {
        public  void LockMethod() {
            synchronized(this)
            {
            }
        }
    }

    或者

    class Test {
        private final Object lock = new Object();
    
        public void LockMethod() {
            synchronized (lock) {
            }
        }
    }

    类级别锁

    若在同步方法中存在静态数据,为保持静态数据线程安全,我们则需使用类级别锁,这意味着,如果在运行时有多个实例的Test,则一次只能在一个实例中的一个线程上执行一个线程LockMethod(),而所有其他实例将被其他线程锁定。针对类级别锁,那么同步块中监视器或锁定对象有如下三种形式:

    class Test {
        public synchronized static void LockMethod() {
        }
    }

    class Test {
        public void LockMethod() {
            synchronized (Test.class)
            {
            }
        }
    }

    class Test {
        private final static Object lock = new Object();
    
        public void LockMethod() {
            synchronized (lock) {
            }
        }
    }

    在这里我主要是看到了上述第二种形式中所使用的锁定对象,由于java和C#语法大多相似,但是这在C#中找不到可对比的东西,我不明白这到底是什么个意思,所以就深入看了些,本以为可以直接查看源码,然而并没有任何反应,看来就是Java中天然存在的了,我去打印发现和获取实例的类名的结果是一样的,我们将这种情况翻译为className.class,这到底是什么意思呢?为何上述第二种形式就是类级别锁定从而保证线程安全了呢?

    System.out.println(Test.class.toString());
    System.out.println(new Test().getClass());

    于是乎我想到看一下所购买的《深入理解Java虚拟机》中对于类加载原理的解释,结果发现:在类加载时机的第一阶段也就是加载阶段,虚拟机会完成3件事情,其中最后一件事情则是在内存中生成一个对应类的java.lang.Class对象,作为方法区这个类的各种数据的入口。换句话说,每个类在JVM中有且只会有唯一的一个java.lang.Class对象,所以我大胆猜测className.class就是获取java.lang.Class对象唯一引用,如此一来就保证始终只有一个线程能够进入同步块。

    总结

    本节我们通过对关键字synchronized实现线程同步做了详细了解,其实并不难,这里我想表达的是看到和C#中不一样的东西,也就是className.class具体是什么意思,同时在用java实现单例模式中也有这种情况,所以详细学习了下,也做个备忘录,可能对大部分学java的童鞋而言确实很简单,我还是处于初级阶段,也是在一步步深入的学习。

  • 相关阅读:
    Java字符集
    ==和equals区别
    web.xml中load-on-startup标签的含义
    使用solrJ管理索引——(十四)
    Solr管理索引库——(十三)
    [置顶] 关于redhat系统yum源的配置1
    设置Oracle用IP远程连接和客户端访问
    jqueryUI中datepicker的使用,解决与asp.net中的UpdatePanel联合使用时的失效问题
    [置顶] 关于redhat系统yum源的配置2
    浅析innodb_support_xa与innodb_flush_log_at_trx_commit
  • 原文地址:https://www.cnblogs.com/CreateMyself/p/12363526.html
Copyright © 2011-2022 走看看