深入理解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关键字同步的是对象而不是方法,我举的列子的确有失偏颇,本人水平有限,如有错误请大家斧正。

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

原文地址:https://www.cnblogs.com/SAM-CJM/p/9810820.html

时间: 2025-01-03 05:48:15

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

synchrozied方法和synchrozied修饰代码块的区别

synchroized是jvm提供的,无需手动控制它可以自动对多线程访问的资源进行加锁与解锁,它可以修饰方法,也可以修饰代码块. 这边博客记录下个人对synchrozied的理解如下: 1.为什么Java要提供synchronized? 当多条线程去对一个类的实例变量进行修改,这时会发生变量的不确定性.为解决这个问题,使用synchronized修饰,使得在某一时刻,只能有一条线程进行操作.实现的方式是加锁与解锁. 2.实例演示多线程访问共享变量产生的问题. public class ManyT

java中setDate(Date date)方法和String与Date之间的转换

经常在开发的过程中遇到这样的问题,从数据库中读出来的数据需要转换为对像或者java bean,此时经常使用到setDate(Date date);这样的方法.感觉这是个很简单而又难受的事情,在这里浪费时间真的是不应该.我这里就记录下我使用过的,方便以后查阅使用. 例如下面的setter方法: private String userId; private boolean isLogin; private Date loginTime; public void setLoginTime(Date l

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

自顶向下彻底理解 Java 中的 Synchronized

阅读本文至少要知道 synchronized 用来是干什么的... 需要的前置知识还有 Java 对象头和 Java 字节码的部分知识. synchronized 的使用 synchronized 有三种使用方式,三种方式锁住的对象是不相同的. 锁分为实例对象锁和 class 对象锁 和 类对象锁,注意这三种锁是不一样的. 修饰实例方法,此时锁住的是对象,锁分为实例对象锁 修饰静态方法,此时锁住的是类对象锁 修饰代码段,此时锁住的是括号中的对象(synchronized(this)),可以是实例

理解java中的volatile关键字

Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了 实现代码线程的安全性.Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分. volatile 写和读的内存语义: 线程 A 写一个 volatile 变量,实质上是线程 A

线程的生命周期 - 理解Java中线程的状态

刚刚开始学cocos2-x,仅仅是按照教程把已经安了一般Android的开发环境的eclipse重新升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 参考博客 D:\cocos2d-x\cocos2d-x-2.2.3\cocos2dx\platform\third_party\android\prebuilt 说说大概的过程: 下载ndk插件,ndk包,cdt插件.最开始我按照书上的下载了cocos2d-x 2.0.1,希望跟书上统一起来,这样以后学习的时候可以参考书上的也不会遇到太

深刻理解Java中的String、StringBuffer和StringBuilder的区别

首先简单地来梳理一下Java中String.StringBuffer和StringBuilder各自的含义. 1.String类 首先,它是线程安全的,即可以用于多线程编程中: 其次,String类的对象是不可变的,即在定义时就确定了,类似String str="Hello";str+="Java";的语句其实是生成了新的对象,只是我们未察觉到而已.但是注意在大量的字符串新建对象时消耗就很可观,这时必须考虑采用StringBuffer或StringBuilder,否

十分钟理解Java中的动态代理

十分钟帮助大家理解Java中的动态代理,什么是动态代理?感兴趣的小伙伴们可以参考一下 若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述1. 什么是代理我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托

读深入理解Java中的String(包括JVM)一文总结和提升

读深入理解Java中的String(包括JVM)一文总结和提升 摘要:String作为Java语言中的字符串模拟类,无论是实际的编程工作还是笔试面试过程,都需要我们都String类非常熟悉,对于String类的大部分字符串操作方法,都必须达到熟练运用的程度才行.但是,笔试和面试过程中,面试官往往喜欢问一些String特性相关的题目,来考察面试者对于String基础知识的掌握是否牢固.(本人尚未研读深入理解JVM这本书,分析JVM都是查看网上资料来分析的,若在接下来的内容有分析不到位的地方请见谅和