广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java中关键字synchronized的使用方法详解
  • 146
分享到

Java中关键字synchronized的使用方法详解

2024-04-02 19:04:59 146人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

synchronized是Java里的一个关键字,起到的一个效果是“监视器锁”~~,它的功能就是保证操作的原子性,同时禁止指令重排序和保证内存的可见性! public clas

synchronized是Java里的一个关键字,起到的一个效果是“监视器”~~,它的功能就是保证操作的原子性,同时禁止指令重排序和保证内存的可见性!


public  class TestDemo {
    static  class Counter{
        public int count = 0;

        public void add(){
            count++;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    counter.add();
                }
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    counter.add();
                }
            }
        };

        //启动两个线程
        t1.start();
        t2.start();
        //等待两个线程结束
        t1.join();
        t2.join();
        System.out.println(counter.count);
    }
}

此时的线程就是不安全的,如何解决呢?

给我们的Counter对象里的add方法加上synchronized关键字,针对这个方法进行了加锁操作。进入代码块(调用方法)自动加锁,出了代码块(方法结束),自动解锁。


public  class TestDemo {
    static  class Counter{
        public int count = 0;
         
         //修饰方法
         synchronized public void add{
             count++;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    counter.add();
                }
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    counter.add();
                }
            }
        };

        //启动两个线程
        t1.start();
        t2.start();
        //等待两个线程结束
        t1.join();
        t2.join();
        System.out.println(counter.count);
    }
}

那么这里的代码是如何保证正确的呢?

使用synchronized 就相当于在我们执行的指令里又加入了2条新指令。

LOCK (加锁)

UNLOCK (解锁)

LOCK操作特性:只有一个线程能执行成功!如果第一个线程执行成功,第二个线程也尝试LOCK,就会阻塞等待,直到第一个线程执行UNLOCK 释放锁~

通过LOCK和UNLOCK 就把 LOAD ADD SAVE 这三个指令,给打包成了一个原子的操作(中间不能被打断,也不能被其他线程穿插)。

这里的加锁也是保证原子性的核心操作,所以线程里的没组指令就会顺序执行,不在穿插执行,就保证了线程1执行完之后再去执行线程2。

举个例子:

就好比张三和李四去ATM里去取钱,当张三进去取钱时,进去后就会锁门,李四就会在外面等待,直到张三取完钱出来后,李四在进去取钱。

synchronized 也会禁止编译器进行“内存可见性”和“指令重排序”的优化~ 同时程序运行的效率就会降低,
也会导致线程之间相互去等待,就涉及到系统的一些调度,也会引入一些时间成本。

synchronized修饰的对象有以下几种:

修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;


public class TestDemo{
    public void methond() {
        // 进入代码块会锁 this 指向对象中的锁;
        // 出代码块会释放 this 指向的对象中的锁
        synchronized (this) {

        }
    }
    public static void main(String[] args) {
        TestDemo demo = new TestDemo();
        demo.methond();
    }
}

修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;


public class TestDemo{
    public synchronized void methond() {

    }
    public static void main(String[] args) {
        TestDemo demo = new TestDemo();
        demo.methond();
        // 进入方法会锁 demo 指向对象中的锁;
        // 出方法会释放 demo 指向的对象中的锁
    }
}

修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;


public class TestDemo{
    public synchronized static void methond() {

    }
    public static void main(String[] args) {
        methond();
        // 进入方法会锁 TestDemo.class 指向对象中的锁;
        //出方法会释放 TestDemo.class 指向的对象中的锁
    }
}

修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。


public class TestDemo{
    public static void methond() {
        // 进入代码块会锁 TestDemo.class 指向对象中的锁;
        //出代码块会释放 TestDemo.class 指向的对象中的锁
        synchronized (TestDemo.class) {

        }
    }
    public static void main(String[] args) {
        TestDemo demo = new TestDemo();
        demo.methond();
    }
}

总结:

  • 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;
  • 如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
  • 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
  • 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

拓展:


public  class TestDemo {

    static   class Counter{
        public int count = 0;

           public void add(){
               synchronized (this){
                   count++;
               }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    synchronized (counter){
                        counter.add();
                    }
                }
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    synchronized (counter){
                        counter.add();
                    }
                }
            }
        };

        //启动两个线程
        t1.start();
        t2.start();
        //等待两个线程结束
        t1.join();
        t2.join();
        System.out.println(counter.count);
    }
}

此时可以看出上述代码,加了两次锁,会发生什么呢?

但是运行代码发现程序依然正确运行?? 为什么

但是上述分析死锁的思路是对的

只是因为synchronized内部使用特殊手段来处理了这种情况 。

这样的操作特性我们叫做 可重入锁

synchronized 内部记录了当前这把锁是哪个线程持有的~

如果当前加锁线程和持有锁的线程是同一个线程~

此时就并不是真的进行“加锁操作”,而是把一个计数器加一;

如果后续该线程继续尝试获取锁,继续判定加锁线程和持有锁线程是不是同一个线程,只要是同一个线程,就不真的加锁,而是计数器+1;

如果该线程调用解锁操作,也不是立刻就解锁,而是计数器减1

直到计数器减成0了,才认为真的要“释放锁”,才允许其他线程来获取锁~~

总结

到此这篇关于Java中synchronized使用的文章就介绍到这了,更多相关Java中synchronized用法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java中关键字synchronized的使用方法详解

本文链接: https://www.lsjlt.com/news/132470.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中关键字synchronized的使用方法详解
    synchronized是Java里的一个关键字,起到的一个效果是“监视器锁”~~,它的功能就是保证操作的原子性,同时禁止指令重排序和保证内存的可见性! public clas...
    99+
    2022-11-12
  • Java 关键字:synchronized详解
    synchronized详解 基本使用源码解析常见面试题好书推荐 基本使用 Java中的synchronized关键字用于在多线程环境下确保数据同步。它可以用来修饰方法和代码块 当一...
    99+
    2023-10-20
    java 开发语言 并发编程 JUC synchronized 原力计划
  • JAVA中native方法与synchronized 关键字
    native , synchronized [@more@]JAVA中native方法 @与羊共舞的狼 Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件...
    99+
    2023-06-03
  • Java中的synchronized关键字
    目录1、synchronized锁的底层实现原理2、基于synchronized实现单例模式3、利用类加载实现单例模式(饿汉模式)1、synchronized锁的底层实现原理 JV...
    99+
    2022-11-12
  • 详解java中private关键字的使用方法
    private 关键字中文就是私有关键字,那么到底要怎么使用呢?1、只能在同一类中访问class A { private String msg="Try to access the private variable outside ...
    99+
    2016-08-22
    java入门 java private
  • 关于java中final关键字的使用方法详解
    一、修饰类被final修饰的类不能被子类继承。//父类Animal public final class Animal{ private int age; //年龄 private String var; //品种 public...
    99+
    2015-04-20
    java final 关键字 使用方法 详解
  • Java super关键字的使用方法详解
    构造方法中的super关键字在Java子类的构造方法中可以通过super关键字来调用父类的构造方法。其用法为: 1) super(); 访问父类中的无参构造函数 2) super (paras…); 访问父类中的成员函数yyy super(...
    99+
    2023-05-31
    java super ava
  • synchronized关键字的使用
    synchronized关键字是java并发编程中常使用的同步锁,用于锁住方法或者代码块,锁代码块时可以是synchronized(this){}、synchronized(Object){}、synchronized(类class){}。...
    99+
    2019-02-24
    java教程 synchronized
  • Java中的synchronized关键字怎么用
    小编给大家分享一下Java中的synchronized关键字怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、synchronized锁的底层实现原理JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。...
    99+
    2023-06-25
  • 如何在Java中使用synchronized关键字
    如何在Java中使用synchronized关键字?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。java基本数据类型有哪些Java的基本数据类型分为:1、整数类...
    99+
    2023-06-14
  • Java关键字synchronized原理与锁的状态详解
    目录一、Java中锁的概念二、同步关键字synchronized特性1、锁消除示例2、锁粗化示例三、synchronized关键字原理1、关于Mark Word2、锁的状态变化(1)...
    99+
    2022-11-13
    Java synchronized Java
  • 【JavaEE】Java中复杂的Synchronized关键字
    目录  一、synchronized的特性 (1)互斥 (2)刷新内存 (3)可重入 二、synchronized的使用 (1)修饰普通方法 (2)修饰静态方法 (3)修饰代码块 三、synchronized的锁机制 (1)基本特点 (2)...
    99+
    2023-09-04
    java java-ee 开发语言 jvm 面试
  • java中synchronized关键字的3种写法实例
    目录预备知识写法一:修饰代码块 写法二:修饰方法写法三:修饰静态方法synchronized原理1. monitor锁定过程2. synchronized锁3. synchroniz...
    99+
    2022-11-12
  • Java多线程之synchronized关键字的使用
    目录一、使用在非静态方法上二、使用在静态方法上三、使用在代码块上四、三种方式的区别4.1 不会互斥4.2 互斥一、使用在非静态方法上 public synchronized vo...
    99+
    2022-11-12
  • java关键字的使用方法
    本篇内容介绍了“java关键字的使用方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在平时写代码的时候我们会经常用到void,我们都知道他...
    99+
    2023-06-19
  • Java this关键字的使用详解
    目录1. 先看一段代码,并分析问题2. 深入理解 this3. this 的注意事项和使用细节4. this 的案例1. 先看一段代码,并分析问题 public class ...
    99+
    2022-11-12
  • Java super关键字的使用详解
    目录1.super介绍2.super的基本使用3.子类和父类方法的调用细节4.super和this的区别1.super介绍 我们可以通过super关键字来实现对父类成员的访问,用来引...
    99+
    2022-11-13
  • Java关键字之this用法详解
    目录一. this关键字1. 简介2. 作用二. 代码案例1. 代表当前类对象2. 调用类中的属性3. 调用类中的方法4. 调用类的构造方法三. 结语一. this关键字 1. 简介...
    99+
    2023-05-19
    Java this关键字 Java关键字 Java this
  • Objective-C中的@Synchronized关键字怎么使用
    这篇文章主要介绍“Objective-C中的@Synchronized关键字怎么使用”,在日常操作中,相信很多人在Objective-C中的@Synchronized关键字怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
    99+
    2023-07-05
  • java线程安全Synchronized关键字怎么使用
    这篇文章主要介绍“java线程安全Synchronized关键字怎么使用”,在日常操作中,相信很多人在java线程安全Synchronized关键字怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jav...
    99+
    2023-06-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作