深入理解Java中的同步静态方法和synchronized(class)代码块的类锁

Posted 真正的小明被占用了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解Java中的同步静态方法和synchronized(class)代码块的类锁相关的知识,希望对你有一定的参考价值。

一.回顾学习内容

 在前面几篇博客中我我们已经理解了synchronized对象锁、对象锁的重入、synchronized方法块、synchronized非本对象的代码块,

 链接:https://www.cnblogs.com/SAM-CJM/category/1314992.html

 我们来总结一下,上面几篇讲到内容:

 1.创建线程类的两个方式:继承Thread类和实现Runable接口。

 2.了解了Thread类的几个基本构造器。

 3.启动多线程时要使用start方法,不要直接调用run方法。

 4.几个多线程中常用的方法。

 5.解决一个共享资源被多个线程调用时采用了synchronized同步化一个对象的方法。

 6.一个线程可以在进入一个同步化的方法时再去进入这个对象的另外一个同步化方法,这个就是对象锁的重入。

 7.为了提高程序的执行效率,我们可以不去直接同步一个方法,直接同步这个方法中有关共享数据的部分,其他部分就是异步执行的。

 8.上一篇讲到了使用synchronized同步一个不是本对象的代码块

二.导入问题

我们到现在使用的synchronized方法同步的都是非静态的方法也就是给一个对象上来一把对象锁,那么我们去给一个静态方法会有什么效果呢?

三.同步将静态方法、同步类资源

其实在Java中给一个静态方法上锁就是给一个类上锁,因为类也可以是一个共享资源。

代码如下:

public class SynClass {//这个类为共享资源
    
    //这个静态方法没有被同步
    public static void fun() throws InterruptedException {
        System.out.println("**************begin**************");
        Thread.sleep(4000);
        System.out.println("**************end**************");
    }

    public static void main(String[] args) {
       ThreadA t1=new ThreadA();
       ThreadA t2=new ThreadA();
       t1.start();
       t2.start();
    }
}
class ThreadA extends Thread {//创建线程
    @Override
    public void run(){
        try {
            SynClass.fun();//调用静态方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果就是出现了线程不同步:

修改代码如下:

    //这个静态方法被同步
   synchronized public static void fun() throws InterruptedException {
        System.out.println("**************begin**************");
        Thread.sleep(4000);
        System.out.println("**************end**************");
    }

结果被同步:

说明类也可以是共享资源,同步静态方法也是在同步类资源。

四.类锁和对象锁的认识

 假如我们有两把锁一把是类锁,一把是对象锁,那么会出现什么情况呢?

 代码如下:

public class SynClassObject {
    //创建一个同步的静态的方法
    public synchronized static void static_fun(){//类锁
        System.out.println("**********静态方法begin*********");
        System.out.println("**********静态方法end***********");
    }
    //创建同步的非静态方法
    public synchronized void notStatic_fun(){//对象锁
        System.out.println("***********非静态方法begin*************");
        System.out.println("***********非静态方法end***************");
    }

    public static void main(String[] args) {
        new SynClassObjectThread1().start();
        new SynClassObjectThread2().start();
    }
}

class SynClassObjectThread1 extends Thread{//这个线程类调用的是同步化的静态方法
    @Override
    public void run(){
        SynClassObject.static_fun();
    }
}

class SynClassObjectThread2 extends Thread{//这个线程类是调用非静态方法
    private SynClassObject synClassObject =new SynClassObject();
    @Override
    public void run(){
        synClassObject.notStatic_fun();
    }
}

 

 结果入下: 明显他是不同步的,因为对象锁和类锁是两把不同的锁。

 同样的道理对于同步静态代码块,也是对类资源实现了一个同步。

 

***************************往期博客纠错******************************

在此要感谢@用户注册了一次老哥,帮助指出了深入理解Java并发synchronized同步化的代码块不是this对象时的操作中的错误,这一篇文章只是为了说明synchronized关键字同步的是对象而不是方法,我举的列子的确有失偏颇,本人水平有限,如有错误请大家斧正。

 ************************************************************************

 

以上是关于深入理解Java中的同步静态方法和synchronized(class)代码块的类锁的主要内容,如果未能解决你的问题,请参考以下文章

深入理解synchronize

深入理解Java虚拟机——同步指令

深入理解Java虚拟机——同步指令

011 深入理解synchronized

深入分析synchronized的实现原理

深入理解使用synchronized同步方法和同步代码块的区别