一张图讲解对象锁和关键字synchronized修饰方法(代码块)

每个对象在出生的时候就有一把钥匙(监视器Monitor),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题。注:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 Monitor。

大家好,又见面了,我是全栈君。

=================================================

对人工智能感兴趣的伙伴,分享一个我朋友的人工智能教程。零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助,点击这里查看教程

=================================================

做一个积极的人

编码、改bug、提升自己

我有一个乐园,面向编程,春暖花开!

每个对象在出生的时候就有一把钥匙(监视器Monitor),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题。

注:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 Monitor。

下面通过一张图片进行讲解:

一、请看图片

图片看不清,请点击这里 : 高清大图

这里写图片描述

二、图片对应的代码

import java.util.Date;

/** * 测试的object类 * * @author:dufy * @version:1.0.0 * @date 2017/9/29 * @email 742981086@qq.com */
public class ObjectTest { 
   


    public synchronized  void methodA(){ 
   
        try { 
   
            System.out.println("This is methodA ...." + Thread.currentThread().getName() + ": " + new Date());
            Thread.sleep(1000);
        } catch (InterruptedException e) { 
   
            e.printStackTrace();
        }

    }

    public void methodB(){ 
   

        System.out.println("This is methodB ...." + Thread.currentThread().getName() + ": " + new Date());
    }

    public synchronized void methodC(){ 
   

        try { 
   
            System.out.println("This is methodC ...." + Thread.currentThread().getName() + ": " + new Date());
            Thread.sleep(3000);
        } catch (InterruptedException e) { 
   
            e.printStackTrace();
        }

    }


}

package com.dufy.concurrentcode;

/** * 测试线程类 * * @author:dufy * @version:1.0.0 * @date 2017/9/29 * @email 742981086@qq.com */
public class ThreadTest extends Thread{ 
   

    public static void main(String[] args) { 
   
        ObjectTest ot = new ObjectTest();
        Thread1 t1 = new Thread1(ot,"thread1");
        Thread2 t2 = new Thread2(ot,"thread2");
        Thread3 t3 = new Thread3(ot,"thread3");
        Thread4 t4 = new Thread4(ot,"thread4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }


    static class Thread1 extends Thread{ 
   
        private ObjectTest objectTest;

        public Thread1(ObjectTest objectTest,String name){ 
   
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() { 
   
            super.run();
            objectTest.methodA();
        }
    }

    static class Thread2 extends Thread{ 
   
        private ObjectTest objectTest;

        public Thread2(ObjectTest objectTest,String name){ 
   
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() { 
   
            super.run();
            objectTest.methodB();
        }
    }

    static class Thread3 extends Thread{ 
   
        private ObjectTest objectTest;

        public Thread3(ObjectTest objectTest,String name){ 
   
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() { 
   
            super.run();
            objectTest.methodA();
        }
    }

    static class Thread4 extends Thread{ 
   
        private ObjectTest objectTest;

        public Thread4(ObjectTest objectTest,String name){ 
   
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() { 
   
            super.run();
            objectTest.methodC();
        }
    }
}

运行结果:

This is methodB ....thread2: Fri Sep 29 23:21:17 CST 2017
This is methodA ....thread1: Fri Sep 29 23:21:17 CST 2017
This is methodC ....thread4: Fri Sep 29 23:21:18 CST 2017
This is methodA ....thread3: Fri Sep 29 23:21:21 CST 2017

注:
1、运行的结果可能和上图讲的线程流程不同,没有关系,只要理解对象锁和synchronized的核心思想就好,线程的运行本来就是具有随机性这个特点。

2、此段代码是同步方法,其实同步的代码块也是一个道理,同步代码块用synchronized(this)时候,当一个线程访问object的一个synchronized(this)同步代码块的时候,其他线程对object中所有其他的synchronized(this)同步的代码块访问都被阻塞 (阻塞的是同步代码块,线程依然可以进入同步代码块的方法)

三、总结说明

  1. 每个对象都有一把锁(对象监视器),关键字synchronized取得锁都是对象锁,而不是把一段代码或方法(函数)当做锁。
  2. 上图所示,哪个线程先执行带有synchronized关键字的方法,哪个线程就持有这个方法所属对象的钥匙。其他线程只能处于等待状态。
  3. 调用关键字synchronized声明的方法,一定是排队运行的。这才是使用synchronized关键字的作用,排队运行,如果有共享资源的话,那么共享资源的读取就是线程安全的。
  4. 如果一个线程持有 object的钥匙,那么其他线程可以访问object对象没有上锁的方法,也就是非synchronized类型的方法。

四、Monitor和线程关系

首先看一下线程和 Monitor之间关系,以 及线程的状态转换图。通过图讲解一下整个过程。

这里写图片描述

上图分为三块:Entry Set(进入区) 、The Owner(拥有区)、Wait Set(等待区)。

  • Entry Set(进入区):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。

  • The Owner(拥有区):表示某一线程成功竞争到对象锁。

  • Wait Set(等待区):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。

上面的内容讲解引自 :Java命令学习系列(二)——Jstack 中关于Monitor的讲解。

参考文章

Java多线程编程核心技术

Java命令学习系列(二)——Jstack


谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你每天开心愉快!


不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

愿你我在人生的路上能都变成最好的自己,能够成为一个独挡一面的人
一张图讲解对象锁和关键字synchronized修饰方法(代码块)

© 每天都在变得更好的阿飞云

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/121137.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • int32_t是什么数据类型_int32_t什么意思

    int32_t是什么数据类型_int32_t什么意思个人理解*_t中的t可以理解为typedefine。由于各个平台中对基本数据的大小定义不一样,为了兼容各个平台,C语言利用预编译和typedef可以让你最有效的维护你的代码。其实这些都不是新的数据类型,为了用户的方便,C99标准的C语言硬件为我们定义了这些类型,我们放心使用。如:int32_t其实就是32位int类型数据。附:C99标准中inttypes.h的内容000010001700…

    2022年9月20日
    0
  • vim输入中文变为乱码

    vim输入中文变为乱码

    2021年8月25日
    53
  • 算法学习笔记之一阶低通滤波算法

    算法学习笔记之一阶低通滤波算法1.一阶滤波算法的原理一阶滤波,又叫一阶惯性滤波,或一阶低通滤波。是使用软件编程实现普通硬件RC低通滤波器的功能。一阶低通滤波的算法公式为:Y(n)=αX(n)(1-α)Y(n-1)式中:α=滤波系数;X(n)=本次采样值;Y(n-1)=上次滤波输出值;Y(n)=本次滤波输出值。一阶低通滤波法采用本次采样值与

    2022年6月11日
    198
  • 圣经中基甸的故事_马热伊基艾

    圣经中基甸的故事_马热伊基艾给定一个包含 n 个点 m 条边的有向图,每条边都有一个流量下界和流量上界。给定源点 S 和汇点 T,求源点到汇点的最小流。输入格式第一行包含四个整数 n,m,S,T。接下来 m 行,每行包含四个整数 a,b,c,d 表示点 a 和 b 之间存在一条有向边,该边的流量下界为 c,流量上界为 d。点编号从 1 到 n。输出格式输出一个整数表示最小流。如果无解,则输出 No Solution。数据范围1≤n≤50003,1≤m≤125003,1≤a,b≤n,0≤c≤d≤21474836

    2022年8月11日
    1
  • 行为动作识别

    行为动作识别随着计算机学科与人工智能的发展和应用,视频分析技术迅速兴起并得到了广泛关注。视频分析中的一个核心就是人体行为识别,行为识别的准确性和快速性将直接影响视频分析系统后续工作的结果。因此,如何提高视频中人体行为识别的准确性和快速性,已成为视频分析系统研究中的重点问题。目前,典型的视频人体行为识别方法主要有:时空兴趣点、密集轨迹等。其中:时空兴趣点,是通过检测视频中的角点、提取角点的特征进行人体行…

    2022年6月21日
    39
  • ASP.NET使用UpdatePanel实现AJAX

    ScriptManager和UpdatePanel控件联合使用可以实现页面异步局部更新的效果。其中的UpdatePanel就是设置页面中异步局部更新区域,它必须依赖于ScriptManager存在,

    2021年12月21日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号