当前位置: 首页 > news >正文

中getname_【136期】你能谈谈Java中 synchronized 对象锁和类锁的区别

点击上方“Java面试题精选”,关注公众号

面试刷图,查缺补漏

>>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅

阶段汇总集合:一百期面试题汇总

synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。

这两者的区别我用代码来演示下

对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。

在Task2 中定义三个方法 doLongTimeTaskA和doLongTimeTaskB是类锁,而doLongTimeTaskC是对象锁。

public class Task2 {

    public synchronized static void doLongTimeTaskA() {
        System.out.println("name = " + Thread.currentThread().getName() + ", begain");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end");
    }

    public synchronized static void doLongTimeTaskB() {
        System.out.println("name = " + Thread.currentThread().getName() + ", begain");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end");
    }

    public synchronized void doLongTimeTaskC() {

        System.out.println("name = " + Thread.currentThread().getName() + ", begain");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end");

    }

三个线程的代码如下:

class ThreadA extends Thread{

    private Task2 mTask2;

    public ThreadA(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskA();
    }
}

class ThreadB extends Thread{

    private Task2 mTask2;

    public ThreadB(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskB();
    }
}

class ThreadC extends Thread{

    private Task2 mTask2;

    public ThreadC(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskC();
    }
}

main函数中执行代码如下:

        Task2 mTask2 = new Task2();
        ThreadA ta = new ThreadA(mTask2);
        ThreadB tb = new ThreadB(mTask2);
        ThreadC tc = new ThreadC(mTask2);

        ta.setName("A");
        tb.setName("B");
        tc.setName("C");

        ta.start();
        tb.start();
        tc.start();

执行的结果如下:

name = A, begain, time = 1487311199783
name = C, begain, time = 1487311199783
name = C, end, time = 1487311200784
name = A, end, time = 1487311200784
name = B, begain, time = 1487311200784
name = B, end, time = 1487311201784

可以看出由于 doLongTimeTaskA和doLongTimeTaskB都是类锁,即同一个锁,所以 A和B是按顺序执行,即同步的。而C是对象锁,和A/B不是同一种锁,所以C和A、B是 异步执行的。(A、B、C代指上面的3中方法)。

更多面试题,欢迎关注公众号 Java面试题精选

我们知道对象锁要想保持同步执行,那么锁住的必须是同一个对象。下面就修改下上面的来证明:

Task2.java不变,修改ThreadA 和 ThreadB 如下:

class ThreadA extends Thread{

    private Task2 mTask2;

    public ThreadA(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskC();
    }
}

class ThreadB extends Thread{

    private Task2 mTask2;

    public ThreadB(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskC();
    }
}

main方法如下:

 Task2 mTaska = new Task2();
 Task2 mTaskb = new Task2();
 ThreadA ta = new ThreadA(mTaska );
 ThreadB tb = new ThreadB(mTaskb );


 ta.setName("A");
 tb.setName("B");

 ta.start();
 tb.start();

结果如下:

name = A, begain, time = 1487311905775
name = B, begain, time = 1487311905775
name = B, end, time = 1487311906775
name = A, end, time = 1487311906775

从结果看来,对象锁锁的对象不一样,分别是mTaska , mTaskb,所以线程A和线程B调用 doLongTimeTaskC 是异步执行的。

但是,类锁可以对类的所有对象的实例起作用。只需修改ThradA 和 ThreadB,main 方法不做改变,修改如下:

class ThreadA extends Thread{

    private Task2 mTask2;

    public ThreadA(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        //mTask2.doLongTimeTaskC();
        mTask2.doLongTimeTaskA();
    }
}

class ThreadB extends Thread{

    private Task2 mTask2;

    public ThreadB(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
       //mTask2.doLongTimeTaskC();
        mTask2.doLongTimeTaskA();
    }
}

结果如下:

name = A, begain, time = 1487312239674
name = A, end, time = 1487312240674
name = B, begain, time = 1487312240674
name = B, end, time = 1487312241674

可以看出 在线程A执行完doLongTimeTaskA方法后,线程B才会获得该类锁接着去执行doLongTimeTaskA。也就是说,类锁对所有的该类对象都能起作用。

往期:100期面试题汇总

总结:

  1. 如果多线程同时访问同一类的 类锁(synchronized 修饰的静态方法)以及对象锁(synchronized 修饰的非静态方法)这两个方法执行是异步的,原因:类锁和对象锁是两种不同的锁。
  2. 类锁对该类的所有对象都能起作用,而对象锁不能。

作者:小猪快跑22
blog.csdn.net/zhujiangtaotaise/article/details/55509939

与其在网上拼命找题? 不如马上关注我们~

8562d12997cd9002e60d1c247d40c3ec.png

相关文章:

  • 加到service中无效_给 COLA 做减法:应用架构中的“弯弯绕设计”
  • set集合 结构体_Swift - 集合(Set)使用详解(附样例)
  • 前端动态获取servlet虚拟路径_Servlet 过滤器和异常处理
  • access中下划线是font_Python中的模块及扩展库
  • mac vs 返回上一步_Figma:使用mac上的字体 | 转换ttc字体文件
  • cmd 访问url_「图解」创建第一个django应用、配置并访问
  • 周星驰经典超清图片_周星驰与刘德华究竟谁更火?为何30年没合作?看王晶的评价...
  • python小老鼠编程_江门Python技能学习价格实惠,python数组学习价格表
  • android layoutinflater获取的textview无法改变值_Android 值得深入思考的几个面试问答分享...
  • gmat模考_GMAT模考成绩不太准原因大盘点
  • 杂牌平板mt6797_10核时代到来 全网通联发科MT6797发布
  • 360加固签名验证_我竟然又相信了360系统补丁!0428无法验证此文件的数字签名!...
  • tps 数据库写并发衡量_NGK TPS是什么?NGK如何实现百万TPS?
  • 数仓建模 项目_老男局 | 尚硅谷技术汇:数仓高频问题解疑
  • lisp封装成vla函数_C#面向对象特性封装、继承、多态,如何在代码编写时使用封装?...
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • Android Volley源码解析
  • Git学习与使用心得(1)—— 初始化
  • Javascript基础之Array数组API
  • JavaScript实现分页效果
  • Java小白进阶笔记(3)-初级面向对象
  • js中的正则表达式入门
  • oschina
  • vagrant 添加本地 box 安装 laravel homestead
  • windows-nginx-https-本地配置
  • 从零搭建Koa2 Server
  • - 概述 - 《设计模式(极简c++版)》
  • 基于webpack 的 vue 多页架构
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 网络应用优化——时延与带宽
  • 小程序button引导用户授权
  • 新手搭建网站的主要流程
  • Java数据解析之JSON
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • #laravel 通过手动安装依赖PHPExcel#
  • (Matlab)使用竞争神经网络实现数据聚类
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (汇总)os模块以及shutil模块对文件的操作
  • (六)Hibernate的二级缓存
  • (三)终结任务
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)可以带来幸福的一本书
  • .net framework profiles /.net framework 配置
  • .NET的微型Web框架 Nancy
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .NET微信公众号开发-2.0创建自定义菜单
  • .net中生成excel后调整宽度
  • @Autowired标签与 @Resource标签 的区别
  • @property @synthesize @dynamic 及相关属性作用探究