侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

synchronized从入门到源码分析

2022-07-05 星期二 / 0 评论 / 0 点赞 / 42 阅读 / 5701 字

微信公众号 : Java患者Synchronizedsynchronized简介synchronized是一个java的关键字,是java语言为了解决并发编程中存在的原子性、可见性和有序性的问题,提供

.

微信公众号 : Java患者

.

Synchronized

synchronized简介

synchronized是一个java的关键字,是java语言为了解决并发编程中存在的原子性、可见性和有序性的问题,提供了一系列跟并发处理有关的关键字,我们今天要来简单了解一下synchronized。

怎么锁?

package com.zero.day3;/*** @Description: synchronized* @Author: Zero* @Date: 2019/12/10*/public class SynchronizedDemo1 {    // 同步方法    public synchronized void wc1 () {        System.out.println("我在上厕所1");    }    // 同步方法 (静态)    public static void wc2 () {        synchronized (SynchronizedDemo1.class) {            System.out.println("我在上厕所2");        }    }    // 同步代码块    public void wc3 () {        synchronized (this) {            System.out.println("我在上厕所3");        }    }}

上面三个简单的方法中都添加了普通同步方法时:锁是当前实例对象synchronized关键字,也就是在同一时间,每个方法只能被单个线程访问,一个厕所同一时间只有有一个人在用。静态同步方法时:锁是当前类的class对象(因为静态方法在对象之前运行,运行静态方法的时候可能都没有对象,所以是当前类的class对象)同步方法块:锁是括号里面的对象

synchronized 实现原理

我们现在对上面的方法进行反编译操作

LINENUMBER 8 L0    ALOAD 0    INVOKESPECIAL java/lang/Object.<init> ()V    RETURN   L1    LOCALVARIABLE this Lcom/zero/day3/SynchronizedDemo1; L0 L1 0    MAXSTACK = 1    MAXLOCALS = 1  // access flags 0x21  public synchronized wc1()V   L0    LINENUMBER 15 L0    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    LDC "/u6211/u5728/u4e0a/u5395/u62401"    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L1    LINENUMBER 16 L1    RETURN   L2    LOCALVARIABLE this Lcom/zero/day3/SynchronizedDemo1; L0 L2 0    MAXSTACK = 2    MAXLOCALS = 1  // access flags 0x9  public static wc2()V    TRYCATCHBLOCK L0 L1 L2 null    TRYCATCHBLOCK L2 L3 L2 null   L4    LINENUMBER 21 L4    LDC Lcom/zero/day3/SynchronizedDemo1;.class    DUP    ASTORE 0    MONITORENTER   L0    LINENUMBER 22 L0    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    LDC "/u6211/u5728/u4e0a/u5395/u62402"    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L5    LINENUMBER 23 L5    ALOAD 0    MONITOREXIT   L1    GOTO L6   L2   FRAME FULL [java/lang/Object] [java/lang/Throwable]    ASTORE 1    ALOAD 0    MONITOREXIT   L3    ALOAD 1    ATHROW   L6    LINENUMBER 24 L6   FRAME CHOP 1    RETURN    MAXSTACK = 2    MAXLOCALS = 2  // access flags 0x1  public wc3()V    TRYCATCHBLOCK L0 L1 L2 null    TRYCATCHBLOCK L2 L3 L2 null   L4    LINENUMBER 29 L4    ALOAD 0    DUP    ASTORE 1    MONITORENTER   L0    LINENUMBER 30 L0    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;    LDC "/u6211/u5728/u4e0a/u5395/u62403"    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V   L5    LINENUMBER 31 L5    ALOAD 1    MONITOREXIT   L1    GOTO L6   L2   FRAME FULL [com/zero/day3/SynchronizedDemo1 java/lang/Object] [java/lang/Throwable]    ASTORE 2    ALOAD 1    MONITOREXIT   L3    ALOAD 2    ATHROW   L6    LINENUMBER 32 L6   FRAME CHOP 1    RETURN   L7    LOCALVARIABLE this Lcom/zero/day3/SynchronizedDemo1; L4 L7 0    MAXSTACK = 2    MAXLOCALS = 3}

我们仔细找找其实可以找到MONITORENTER跟MONITOREXIT这两个单词,接下来,我就用比较简单粗暴的语言来给大家随便说说这个过程。假如这个时候呢有三个线程Thread1,Thread2, Thread3都同时来调用一个方法,那么代码肯定是共享的啦,那么当这个方法function没有加锁的时候,Thread1来执行这个代码,执行到一半Thread2也可以来执行,Thread3当然也可以执行。当这个方法function加了锁之后就不一样了,这代码编译就会产生这两个指令,当Thread1来抢到CPU的执行权之后就来执行这个方法了啊,碰到这个MONITORENTER的时候,这就厉害了啊!其他的线程都给调用了wait方法,大家都知道当线程调用了wait方法之后,就会进入等待状态,谁都救不了它们,这个时候Thread1就自己大摇大摆地执行完了这个加锁的方法,自然就有了MONITOREXIT指令,这个时候线程还在等待?怎么办,当线程处于wait的时候我们都知道会调用notifyAll方法去唤醒所有的其他线程,这个时候所有的线程就苏醒了继续执行。

结语

小编是一枚Java Coder,业余写文章,现主营微信公众号《Java患者》,喜欢的话关注我的公众号或者加我微信我们一起学习Java

.

.

广告 广告

评论区