文章六:Java中的同步机制

news2024/9/22 9:52:36

目录

6.1 引言

同步机制在并发编程中的作用

本文的内容结构

6.2 synchronized关键字

使用synchronized进行线程同步

同步方法示例

synchronized的底层实现

6.3 显式锁

ReentrantLock的使用和优势

ReentrantLock示例

Condition接口和多条件等待的示例

Condition示例

6.4 读写锁

ReadWriteLock的概念和应用

ReentrantReadWriteLock的示例代码

ReentrantReadWriteLock示例

结论


6.1 引言

同步机制在并发编程中的作用

在并发编程中,多线程同时访问和修改共享资源时可能会导致数据不一致或竞争条件。为了确保线程安全,Java 提供了多种同步机制来协调线程对共享资源的访问。同步机制在多线程环境中起着至关重要的作用,能够防止数据竞态条件,保证数据的一致性和正确性。

本文的内容结构

本文将介绍 Java 中常用的同步机制,主要内容包括:

  1. 使用 synchronized 关键字进行线程同步
  2. 显式锁的使用
  3. 读写锁的概念和应用

6.2 synchronized关键字

使用synchronized进行线程同步

synchronized 关键字是 Java 提供的最基础的同步机制,用于确保同一时间只有一个线程可以访问同步代码块或方法。可以通过两种方式使用 synchronized 关键字:

  1. 同步方法:在方法声明中使用 synchronized 关键字。
  2. 同步代码块:在方法内部使用 synchronized 代码块。
同步方法示例
public class SynchronizedMethodDemo {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

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

        Thread thread1 = new Thread(demo::increment);
        Thread thread2 = new Thread(demo::increment);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("Final count: " + demo.count);
    }
}

同步代码块示例

public class SynchronizedBlockDemo {
    private int count = 0;
    private final Object lock = new Object();

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }

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

        Thread thread1 = new Thread(demo::increment);
        Thread thread2 = new Thread(demo::increment);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("Final count: " + demo.count);
    }
}

synchronized的底层实现

synchronized 关键字的底层实现是基于对象头中的监视器锁(Monitor Lock)。每个对象都有一个监视器,当线程进入同步代码块或方法时,会尝试获取对象的监视器锁。如果监视器锁已经被其他线程持有,则当前线程会被阻塞,直到监视器锁被释放。

Java 虚拟机(JVM)通过以下几种锁优化技术来提高 synchronized 的性能:

  1. 偏向锁(Biased Locking):偏向锁是为了优化线程多次获得同一锁的场景,减少不必要的同步操作。
  2. 轻量级锁(Lightweight Locking):轻量级锁在锁竞争不激烈时,通过使用CAS操作避免重量级锁的开销。
  3. 重量级锁(Heavyweight Locking):当锁竞争激烈时,JVM 会使用重量级锁来保证线程安全。

6.3 显式锁

ReentrantLock的使用和优势

ReentrantLockjava.util.concurrent.locks 包中的一个显式锁类,它提供了比 synchronized 更加灵活的同步机制。ReentrantLock 支持可重入、可中断、公平锁等特性。

ReentrantLock示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

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

        Thread thread1 = new Thread(demo::increment);
        Thread thread2 = new Thread(demo::increment);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("Final count: " + demo.count);
    }
}

Condition接口和多条件等待的示例

Condition 接口提供了比 Object 类的 waitnotifynotifyAll 方法更加强大的线程等待/通知机制。通过使用 Condition,可以实现多条件等待。

Condition示例
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionDemo {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private boolean ready = false;

    public void await() throws InterruptedException {
        lock.lock();
        try {
            while (!ready) {
                condition.await();
            }
            System.out.println("Thread is proceeding...");
        } finally {
            lock.unlock();
        }
    }

    public void signal() {
        lock.lock();
        try {
            ready = true;
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

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

        Thread thread1 = new Thread(() -> {
            try {
                demo.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread thread2 = new Thread(demo::signal);

        thread1.start();
        Thread.sleep(1000); // 确保thread1先启动并等待
        thread2.start();

        thread1.join();
        thread2.join();
    }
}

6.4 读写锁

ReadWriteLock的概念和应用

ReadWriteLock 提供了一种分离读写锁的机制,允许多个读线程同时访问共享资源,但在写线程访问共享资源时,所有的读线程和其他写线程都将被阻塞。这种机制可以提高读多写少场景下的并发性能。

ReentrantReadWriteLock的示例代码

ReentrantReadWriteLockReadWriteLock 接口的一个具体实现类,提供了可重入的读写锁。

ReentrantReadWriteLock示例
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    private int value = 0;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public void read() {
        lock.readLock().lock();
        try {
            System.out.println("Read value: " + value);
        } finally {
            lock.readLock().unlock();
        }
    }

    public void write(int newValue) {
        lock.writeLock().lock();
        try {
            value = newValue;
            System.out.println("Written value: " + value);
        } finally {
            lock.writeLock().unlock();
        }
    }

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

        Thread writer = new Thread(() -> demo.write(42));
        Thread reader1 = new Thread(demo::read);
        Thread reader2 = new Thread(demo::read);

        writer.start();
        writer.join(); // 确保写线程先执行

        reader1.start();
        reader2.start();

        reader1.join();
        reader2.join();
    }
}

在这个示例中,ReadWriteLock 确保了在写操作进行时没有读操作进行,而读操作可以并发执行。

结论

本文详细介绍了Java中的同步机制,包括synchronized关键字、显式锁ReentrantLock、以及读写锁ReentrantReadWriteLock。通过这些同步机制,开发者可以有效地协调多线程对共享资源的访问,确保线程安全。在实际开发中,根据具体需求选择合适的同步机制,可以大大提升并发编程的效率和可靠性。希望本文对你有所帮助,敬请期待专栏的下一篇文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1935465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

叶师傅:区区1万张表就把MySQL给整崩溃了

自Oracle发布MySQL9.0以来,貌似对MySQL的吐槽有所增加。作为吃瓜群众的我,来跟个风. 以下文章来源于老叶茶馆 ,作者YeJinrong/叶金荣 Percona 资深工程师 Marco Tusa 近日爆料称,升级到 MySQL 8.0.38 版本后,当实例中…

【运维资料】智慧项目运维服务方案(2024Word直接套用完整版)

信息化项目运维服务方案(投标,实施运维,交付) 1.项目整体介绍 2.服务简述 3.资源提供 软件全过程性,标准型,规范性文档(全套资料包)获取:本文末个人名片直接获取&#xf…

MaxSite CMS v180 文件上传漏洞(CVE-2022-25411)

前言 CVE-2022-25411 是一个影响 Maxsite CMS v180 的远程代码执行漏洞。攻击者可以通过上传一个特制的 PHP 文件来利用这个漏洞,从而在受影响的系统上执行任意代码。 漏洞描述 该漏洞存在于 Maxsite CMS v180 的文件上传功能中。漏洞利用主要通过允许上传带有危…

自动驾驶-定位概述

假设有一张全球的高精度地图,定位的任务是确定车辆在这张高精度地图上的位置。gps精度在1到3米,由于不能完全信任gps,必须找到另一种方法来准确的确定车辆在地图上的位置。 最常用的方法是将所看到的内容和地图上显示的内容进行比较 车辆坐…

C#医学影像管理系统源码(VS2013)

目录 一、概述 二、系统功能 系统维护 工作站 三、功能介绍 影像采集 统计模块 专业阅片 采集诊断报告 报告管理 一、概述 医学影像存储与传输系统(PACS)是一种集成了影像存储、传输、管理和诊断功能的系统。它基于数字化成像技术、计算机技术和…

探索二进制翻译,openKylin成功在RISC-V平台运行X86架构软件!

众所周知,在新的指令集架构发展初期,往往采用兼容其他架构软件的方法来拓展自身生态体系,如苹果公司的Rosetta 2和微软的Arm64EC,都是将X86架构软件运行在ARM架构的系统之上。 RISC-V作为一个新兴的指令集架构,亟需软…

css技巧混合模式

看上面这个神奇的效果,文字在黑色背景里面显示为白色,而在白色的背景里面显示为黑色,这就是文字智能适配背景。 看到这样的需求,大多数人第一时间想到的是,文字元素有两个,是完全重叠的两层,一…

Pycharm 报错 Environment location directory is not empty 解

删除项目中ven文件夹(已存在的),然后再添加新的ven虚拟环境就可以了

链表面试练习习题(Java)

1. 思路: 创建两个链表,一个用来记录小于x的结点,一个用来记录大于等于x的结点,然后遍历完原链表后,将小于x的链表和大于等于x的链表进行拼接即可 public class Partition { public ListNode partition(ListNode pH…

【JVM】JVM调优练习-随笔

JVM实战笔记-随笔 前言字节码如何查看字节码文件jclasslibJavapArthasArthurs监控面板Arthus查看字节码信息 内存调优内存溢出的常见场景解决内存溢出发现问题Top命令VisualVMArthas使用案例 Prometheus Grafana案例 堆内存情况对比内存泄漏的原因:代码中的内存泄漏并发请求问…

自动化测试中如何应对网页弹窗的挑战!

在自动化测试中,网页弹窗的出现常常成为测试流程中的一个难点。无论是警告框、确认框、提示框,还是更复杂的模态对话框,都可能中断测试脚本的正常执行,导致测试结果的不确定性。本文将探讨几种有效的方法来应对网页弹窗的挑战&…

IDEA中内敛局部变量对话窗是什么?

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

【Hive SQL 每日一题】找出各个商品销售额的中位数

文章目录 测试数据需求说明需求实现方法1 —— 升序计算法方法2 —— 正反排序法 补充 测试数据 -- 创建 orders 表 DROP TABLE IF EXISTS orders; CREATE TABLE orders (order_id INT,product_id INT,order_date STRING,amount DOUBLE );-- 插入 orders 数据 INSERT INTO ord…

【Linux】Linux环境设置环境变量操作步骤

Linux环境设置环境变量操作步骤 在一些开发过程中本地调试经常需要依赖环境变量的参数,但是怎么设置对小白来说有点困难,今天就介绍下具体的操作步骤,跟着实战去学习,更好的检验自己的技术水平,做技术还是那句话&…

HTML+JS+CSS计算练习

可填 题目数量 数字范围 计算符号 题目做完后会弹窗提示正确率、用时 效果图 源代码在图片后面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…

读AI新生:破解人机共存密码笔记18读后总结与感想兼导读

1. 基本信息 读AI新生&#xff1a;破解人机共存密码 斯图尔特罗素 著 中信出版社,2020年8月出版 1.1. 读薄率 书籍总字数301千字&#xff0c;笔记总字数44614字。 读薄率44614301000≈14.8% 1.2. 读厚方向 千脑智能 脑机穿越 未来呼啸而来 虚拟人 AI3.0 新机器人 …

月亮和Pandas -- 开源项目的挑战与机遇

毛姆的《月亮和六便士》讲述了这样一个故事&#xff0c;一个富有的英国股票经纪人&#xff0c;思特里克兰德&#xff0c;为了追求艺术和美&#xff0c;放弃自己的生活和家庭&#xff0c;来到巴黎&#xff0c;以艺术家的身份过着贫穷却目中无人的充足的生活&#xff0c;最终留下…

芯科科技第五届物联网开发者大会走进世界各地,巡回开启注册

中国&#xff0c;北京 – 2024年7月18日 – 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;今日宣布&#xff0c;其2024年Works With开发者大会现正开放注册…

一文带你摸清SaaS服务与开源知识库的区别

在当今数字化转型的浪潮中&#xff0c;SaaS服务与开源知识库作为推动行业进步的两股重要力量&#xff0c;在多个方面展现出显著的区别。SaaS以其即用即付的便捷性、持续更新维护的优势&#xff0c;成为现代企业提升效率的首选&#xff1b;而开源知识库则凭借开放共享、自由定制…

SpringMVC注解全解析:构建高效Web应用的终极指南 (上)

SpringMVC 是一个强大的 Web 框架&#xff0c;广泛应用于 Java Web 开发中。它通过注解简化了配置&#xff0c;增强了代码的可读性。本文将全面解析 SpringMVC 中常用的注解及其用法&#xff0c;帮助你构建高效的 Web 应用。 一. MVC介绍 MVC 是 Model View Controller 的缩写…