IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 深入理解使用synchronized同步方法和同步代码块的区别 -> 正文阅读

[Java知识库]深入理解使用synchronized同步方法和同步代码块的区别

一.代码块和方法之间的区别

首先需要知道代码块和方法有什么区别:

构造器和方法块,构造器可以重载也就是说明在创建对象时可以按照不同的构造器来创建,那么构造器是属于对象,而代码块呢他是给所有的对象初始化的。底下看一个列子:

package com.bgi;

public class Constructor_Methodblock  {
    private int num;
    private String str;
    //构造器
    public Constructor_Methodblock(int num,String str){
        System.out.println("\n************构造器****************");
        System.out.println("在进入构造器之前成员变量的值为num:"+this.num+"str: "+this.str);
        this.str=str;
        this.num=num;
        System.out.println("赋值之后num为"+num+"str为"+str);
    }
    //方法块
    {
        System.out.println("\n************代码块****************");
        System.out.println("在进入方法块之前成员变量的值为num:"+num+"str: "+str);
        num=1;
        str="li";
        System.out.println("赋值之后num为"+num+"str为"+str);
    }

    public static void main(String[] args) {
        new Constructor_Methodblock(2,"sun");
    }
}

结果为:

在这里插入图片描述
发现代码块比构造器早执行,而且代码块是所有的对象都要执行的。

现在我们对代码块和方法有了一定的了解,那么同步方法有什么缺点使得我们需要同步代码块呢?

二.同步方法的缺点

来想象一个这样的情况:一个方法其中有一部分是需要计算数据花费时间不是那么长但是还有一部分他不需要处理数据但是他需要花费大量的时间,那么如果我们直接将这个方法同步化会导致整体的代码性能下降,而我们仅仅将这个计算数据部分同步保证共享数据计算没有问题,那么代码性能是不是就上去了呢?

来看直接同步化方法:
package com.bgi;

public class SynFun extends Thread {
    private int num=10;//共享数据
    @Override
    public void run(){
        try {
            this.fun();//调用同步方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void fun() throws InterruptedException {
        //使用睡眠来模拟一下复杂但是对数据处理没有关系的部分,睡眠三秒
        Thread.sleep(2000);
        System.out.println("修改前的num为"+num);
        num--;
        System.out.println("修改后的num为"+num);
        System.out.println("*************");
    }

    public static void main(String[] args) {

        SynFun synFun=new SynFun();
        Thread t1=new Thread(synFun);
        Thread t2=new Thread(synFun);
        //synchronized锁一旦被一个线程持有,其他试图获取该锁的线程将被阻塞,所以只能线程只能一个个的执行
        t1.start();
        t2.start();

    }
}

结果为:
在这里插入图片描述出现结果时,先等待了三秒出现了第一个结果,在等待了三秒又出现了第二个结果。

改进一下:
public void fun() throws InterruptedException {
//使用睡眠来模拟一下复杂但是对数据处理没有关系的部分,睡眠三秒
Thread.sleep(3000);
synchronized (this){
System.out.println(“修改前的num为”+num);
num–;
System.out.println(“修改后的num为”+num);
}
System.out.println("*************");
}

就是利用同步化代码块,将共享数据处理的部分同步起来,而其他的部分就让他去交叉运行吧。
结果是一样的,但是出现结果就是三秒以后直接出现两个答案,说明整体性能直接上去了。





synchronized关键字介绍

1、synchronized作用

原子性:synchronized保证语句块内操作是原子的
可见性:synchronized保证可见性(通过“在执行unlock之前,必须先把此变量同步回主内存”实现)
有序性:synchronized保证有序性(通过“一个变量在同一时刻只允许一条线程对其进行lock操作”)

2、synchronized的使用

修饰实例方法,对当前实例对象加锁
修饰静态方法,多当前类的Class对象加锁
修饰代码块,对synchronized括号内的对象加锁

实现原理

1、jvm基于进入和退出Monitor对象来实现方法同步和代码块同步

方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。JVM可以从方法常量池中的方法表结构(method_info Structure) 中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。当方法调用时,调用指令将会 检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor(虚拟机规范中用的是管程一词), 然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放monitor。

代码块的同步是利用monitorenter和monitorexit这两个字节码指令。它们分别位于同步代码块的开始和结束位置。当jvm执行到monitorenter指令时,当前线程试图获取monitor对象的所有权,如果未加锁或者已经被当前线程所持有,就把锁的计数器+1;当执行monitorexit指令时,锁计数器-1;当锁计数器为0时,该锁就被释放了。如果获取monitor对象失败,该线程则会进入阻塞状态,直到其他线程释放锁。

这里要注意:

synchronized是可重入的,所以不会自己把,自己锁死
synchronized锁一旦被一个线程持有,其他试图获取该锁的线程将被阻塞。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 21:56:42  更:2022-03-17 22:00:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:24:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码