对象级别锁 vs 类级别锁(Java)

前言

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

对象级别锁 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(),而全部其余实例将被其余线程锁定。针对类级别锁,那么同步块中监视器或锁定对象有以下三种形式:this

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

spa

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对象惟一实例的引用,如此一来就保证始终只有一个线程可以进入同步块。code

总结

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

相关文章
相关标签/搜索