Java关键字之synchronized详解【Java多线程必备】

这篇具有很好参考价值的文章主要介绍了Java关键字之synchronized详解【Java多线程必备】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

点击 Mr.绵羊的知识星球 解锁更多优质文章。

目录

一、介绍

二、特性

1. 线程安全

2. 互斥访问

3. 可重入性

4. 内置锁

三、实现原理

四、和其他锁比较

1. 优点

2. 缺点

五、注意事项和最佳实践

六、使用案例

1. 案例一

2. 案例二


一、介绍

    synchronized是Java中最基本的同步机制之一,它通过在代码块或方法上添加synchronized关键字来实现线程的同步和互斥。使用synchronized可以确保多个线程在访问共享资源时不会发生冲突。

二、特性

1. 线程安全

    使用synchronized可以确保多个线程在访问共享资源时不会发生冲突。

2. 互斥访问

    同一时刻只能有一个线程访问共享资源。

3. 可重入性

    同一个线程可以多次获得同一把锁,避免死锁。

4. 内置锁

    每个Java对象都有一个内置锁,而synchronized就是使用对象的内置锁。

三、实现原理

    在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。

java synchronized,Java,多线程必备,java

    synchronized是基于Java对象头中的标志位实现的。在Java对象头中,有两个标志位用于存储synchronized锁的信息:一个是表示当前对象是否被锁定的标志位,另一个是表示持有锁的线程的标识符。

    当一个线程尝试获得一个被synchronized锁保护的资源时,JVM会首先检查该对象的锁标志位。如果锁标志位为0,表示该对象没有被锁定,JVM会将锁标志位设置为1,并将持有锁的线程标识符设置为当前线程的标识符。如果锁标志位为1,表示该对象已经被其他线程锁定,当前线程会进入阻塞状态,等待其他线程释放锁。

    当一个线程释放一个被synchronized锁保护的资源时,JVM会将锁标志位设置为0,表示该对象已经被释放。同时,JVM会唤醒等待该对象锁的其他线程,使它们可以继续竞争锁。

四、和其他锁比较

    synchronized和其他锁相比,具有以下优点和缺点:

1. 优点

    (1)简单易用:synchronized是Java内置的锁机制,使用起来非常简单,不需要额外的依赖。

    (2)高效:synchronized的实现非常高效,不会消耗过多的系统资源。

2. 缺点

    (1)可重入性有限:虽然synchronized支持可重入性,但是同一个线程在持有锁的同时,不能获取该对象的其他锁。

    (2)不能协调多个线程:synchronized只能协调两个线程之间的同步,不能协调多个线程之间的同步。如果需要协调多个线程之间的同步,需要使用其他的同步机制,如Lock、Semaphore、CountDownLatch等。

    (3)灵活性差:synchronized只支持两种锁的获取方式:对象锁和类锁。如果需要更灵活的锁获取方式,需要使用其他的同步机制。

    与其他锁相比,synchronized是一种简单、高效的同步机制,适用于大多数的并发场景。但是在一些特殊的场景下,需要使用其他的同步机制来协调多个线程之间的同步。

五、注意事项和最佳实践

1. synchronized是一种非常重要的同步机制,但是不要滥用,因为过多的同步会导致程序的性能下降,甚至引发死锁等问题。

2. 在使用synchronized时,尽量避免对锁对象进行修改,因为这样会破坏锁的语义,从而导致不可预料的问题。

3. 要考虑锁的粒度问题。如果锁的粒度过粗,会导致线程的竞争过于激烈,从而降低程序的并发性能;如果锁的粒度过细,会导致锁的竞争过多,从而增加线程的上下文切换开销。因此,需要根据实际情况合理地确定锁的粒度。

4. 尽量使用局部变量代替成员变量,因为局部变量的访问速度比成员变量快,从而可以提高程序的并发性能。

5. 在使用synchronized时,要注意锁的可见性问题。如果一个变量被多个线程共享,并且其中一个线程修改了这个变量的值,那么其他线程可能无法看到这个修改,从而导致不一致的结果。因此,在使用synchronized时,要确保被同步的变量对所有线程都可见。

六、使用案例

1. 案例一

    (1) 场景

    实现一个计数器,在increment()和decrement()方法上使用了synchronized关键字,保证了成员变量count线程安全。

    (2) 代码

/**
 * Counter 计数器
 *
 * @author wxy
 * @date 2023-04-05
 */
public class Counter {
    private int count = 0;

    /**
     * 将count+1
     */
    public synchronized void increment() {
        count++;
    }

    /**
     * 将count-1
     */
    public synchronized void decrement() {
        count--;
    }

    public synchronized int getCount() {
        return count;
    }
}

class CounterTest {
    private static final int FOR_COUNT = 100;

    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        // 线程t1将count+1执行1000次
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < FOR_COUNT; i++) {
                counter.increment();
            }
        });

        // 线程t1将count-1执行1000次
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < FOR_COUNT; i++) {
                counter.decrement();
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(counter.getCount());
    }
}

    在上面的示例中,Counter类表示一个计数器,提供了increment()、decrement()、getCount()方法,用于对计数器进行增加、减少和获取操作。这三个方法都使用了synchronized关键字,确保在多线程环境下对计数器进行同步和互斥访问。

2. 案例二

    (1) 场景

    使用synchronized的案例是实现线程安全的单例模式。

    单例模式是一种常用的设计模式,(关于单例设计模式,看这篇文章),它确保一个类只有一个实例,并且提供了全局的访问点。然而,在多线程环境下,如果不采取措施,可能会创建多个实例,从而违背了单例模式的原则。因此,需要使用synchronized来确保线程安全。

    (2) 代码

/**
 * 单例设计模式
 * 采用加锁实现, 每次调用方法都加锁效率低(不推荐)
 *
 * @author wxy
 * @date 2023-04-05
 */
public class SingletonCase1 {
    private static SingletonCase1 instance;

    private SingletonCase1() {
        // 私有构造方法
    }

    public static synchronized SingletonCase1 getInstance() {
        if (instance == null) {
            instance = new SingletonCase1();
        }
        return instance;
    }
}

    在上面的示例中,getInstance()方法使用了synchronized关键字,这种方式可以确保线程安全,但是肯定会导致程序的性能下降,因为每次调用getInstance()方法时都会进行同步。为了解决这个问题,可以使用双重检查锁定(double-checked locking)的方式,将同步的粒度降到方法内部。

    下面是一个使用双重检查锁定实现线程安全的单例模式的示例:

/**
 * 单例设计模式
 * 采用双重检锁实现(推荐)
 *
 * @author wxy
 * @date 2023-04-05
 */
public class SingletonCase2 {
    /**
     * volatile修饰: 保证该变量具有可见性、禁止指令重排
     */
    private static volatile SingletonCase2 instance;

    private SingletonCase2() {
        // 私有构造方法
    }

    public static SingletonCase2 getInstance() {
        if (instance == null) {
            synchronized (SingletonCase2.class) {
                if (instance == null) {
                    instance = new SingletonCase2();
                }
            }
        }
        return instance;
    }
}

    在上面的示例中,getInstance()方法首先检查instance是否为null,如果为null,才会进入同步块。在同步块内部,再次检查instance是否为null,如果为null,才会创建一个Singleton对象。由于加入了volatile关键字,确保instance的可见性,从而避免了线程安全问题。同时,通过双重检查锁定的方式,将同步的粒度降到方法内部,提高了程序的性能。

参考文章

1. synchronized详解文章来源地址https://www.toymoban.com/news/detail-821836.html

到了这里,关于Java关键字之synchronized详解【Java多线程必备】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java并发之synchronized关键字和Lock接口

    欢迎点赞阅读,一同学习交流,有疑问请留言 。 GitHub上也有开源 JavaHouse,欢迎star 当开发过程中,我们遇到并发问题。怎么解决? 一种解决方式,简单粗暴:上锁。将千军万马都给拦下来,只允许一个人过独木桥。书面意思就是将并行的程序变成串行的程序。现实的锁有门锁

    2024年02月08日
    浏览(31)
  • Java 八股文面试过程系列之synchronized关键字

    本文通过一场虚拟的面试对话,详细解析了Java中的synchronized关键字。从基本用法到底层实现原理,再到性能优化策略,全面提升您对同步机制的理解。

    2024年02月07日
    浏览(39)
  • 【Synchronized关键字】

    Synchronized是Java中的,它用于控制多线程之间的访问,保证同一时刻只有一个线程可以执行被锁定的代码块或方法。在多线程编程中,Synchronized是一种非常重要的机制,它可以避免多个线程同时访问共享资源而产生数据不一致性的问题。 Synchronized有两种使用方式:对代

    2024年02月08日
    浏览(34)
  • 并发——synchronized 关键字

    synchronized 解决的是多个线程之间访问资源的同步性, synchronized 可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。 另外,在 Java 早期版本中, synchronized 属于 重量级锁 ,效率低下。 为什么呢? 因为监视器锁(monitor)是依赖于底层的操作系

    2024年02月13日
    浏览(26)
  • 多线程系列(四) -volatile关键字使用详解

    在上篇文章中,我们介绍到在多线程环境下,如果编程不当,可能会出现程序运行结果混乱的问题。 出现这个原因主要是,JMM 中主内存和线程工作内存的数据不一致,以及多个线程执行时无序,共同导致的结果。 同时也提到引入 synchronized 同步锁,可以保证线程同步,让多

    2024年02月21日
    浏览(50)
  • Java多线程系列——同步关键字

    目录 一、线程安全和数据不一致性 二、synchronized的作用 三、synchronized工作原理 四、锁的级别 五、synchronized的优点与缺点 六、实战应用 七、总结 在Java中, synchronized 是并发编程中的一个基本构建块,用于控制多个线程对共享资源的访问,以确保数据的一致性

    2024年02月21日
    浏览(32)
  • 《吊打面试官系列》从源码全面解析 synchronized 关键字的来龙去脉

    👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主 📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙、Spring从成神到升仙系列 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一

    2023年04月16日
    浏览(37)
  • 详解Java的static关键字

    不依赖于对象实例:静态方法不需要依赖于任何对象实例,因为它们与具体的对象实例无关联。这意味着在没有创建对象实例的情况下,就可以直接通过类名访问或调用静态方法。 可以访问静态成员:静态方法可以访问类的静态成员(静态字段和静态方法),但不能访问非静

    2024年02月05日
    浏览(39)
  • 【Java 基础】构造方法和 this 关键字详解

    《 Java 零基础入门到精通 》 专栏持续更新中。通过本专栏你将学习到 Java 从 入门 到 进阶 再到 实战 的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。 订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java

    2023年04月14日
    浏览(39)
  • 【Java 基础】引用型数组、Java 继承、super 关键字详解

    《 Java 零基础入门到精通 》 专栏持续更新中。通过本专栏你将学习到 Java 从 入门 到 进阶 再到 实战 的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。 订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java

    2024年02月03日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包