Java 中同步机制的几种方式及使用

news2024/11/30 0:37:36

在Java中,同步机制是用来解决多线程并发访问共享资源的问题。如果多个线程同时访问共享资源,可能会导致数据不一致、死锁等问题。Java中提供了多种同步机制,例如synchronized关键字、Lock接口、Semaphore类、CountDownLatch类等。本文将介绍Java中常见的同步机制,并讨论它们的使用方法和注意事项。

在这里插入图片描述

synchronized关键字

synchronized关键字是Java中最常见的同步机制。它可以用于同步方法和同步代码块,使得多个线程可以按照一定的顺序访问共享资源,从而避免线程之间的竞争和冲突。

同步方法

在Java中,可以使用synchronized关键字来同步方法。如果一个方法被标记为synchronized,那么同一时间只能有一个线程执行该方法。其他线程必须等待该线程执行完毕后才能继续执行。

public synchronized void foo() {
    // Synchronized method implementation
}

这个示例中,我们定义了一个同步方法foo。由于该方法被标记为synchronized,因此同一时间只能有一个线程执行该方法。

同步代码块

除了同步方法,还可以使用synchronized关键字来同步代码块。如果一个代码块被标记为synchronized,那么同一时间只能有一个线程执行该代码块。其他线程必须等待该线程执行完毕后才能继续执行。

public void foo() {
    synchronized (this) {
        // Synchronized code block implementation
    }
}

这个示例中,我们定义了一个同步代码块,使用this作为锁对象。由于该代码块被标记为synchronized,因此同一时间只能有一个线程执行该代码块。

锁对象

在Java中,每个对象都有一个锁对象。当一个线程访问一个对象时,它会自动获取该对象的锁对象。如果该对象已经被其他线程占用,则当前线程必须等待,直到锁对象被释放为止。

public class MyObject {
    public synchronized void foo() {
        // Synchronized method implementation
    }
}

public class MyThread extends Thread {
    private MyObject obj;

    public MyThread(MyObject obj) {
        this.obj = obj;
    }

    public void run() {
        obj.foo();
    }
}

MyObject obj = new MyObject();
MyThread t1 = new MyThread(obj);
MyThread t2 = new MyThread(obj);
t1.start();
t2.start();

这个示例中,我们定义了一个MyObject类,其中包含一个同步方法foo。我们创建了两个线程t1和t2,它们都访问同一个MyObject对象。由于该对象的锁对象只有一个,因此t1和t2必须按照一定的顺序访问该对象。

注意事项

使用synchronized关键字时需要注意以下几点:

  • 锁对象的范围应该尽量小,以减少锁的竞争和等待时间。
  • 锁对象可以是任意对象,但是多个线程必须使用同一个锁对象。
  • 如果一个方法或代码块被标记为synchronized,那么它的性能可能会受到影响,因为其他线程必须等待该线程执行完毕后才能继续执行。
  • 如果一个线程执行了一个synchronized方法或代码块,那么它会自动释放该对象的锁对象。如果一个线程执行了一个非同步方法或代码块,那么它并不会自动释放该对象的锁对象。

Lock接口

除了synchronized关键字,Java还提供了Lock接口来实现同步机制。Lock接口提供了更多的功能和灵活性,可以满足更多的需求和场景。

获取锁和释放锁

Lock接口提供了两个方法来获取锁和释放锁:

  • lock():获取锁,如果锁已经被占用,则当前线程会等待,直到锁被释放。
  • unlock():释放锁。
Lock lock = new ReentrantLock();
lock.lock();
try {
    // Synchronized code block implementation
} finally {
    lock.unlock();
}

这个示例中,我们使用ReentrantLock类来创建一个锁对象,然后使用lock()方法获取锁,使用try-finally语句块来执行同步代码块,最后使用unlock()方法释放锁。

尝试获取锁

Lock接口还提供了一个tryLock()方法,用于尝试获取锁。如果锁已经被占用,则该方法会立即返回false,而不是等待。

java

Copy

Lock lock = new ReentrantLock();
if (lock.tryLock()) {
    try {
        // Synchronized code block implementation
    } finally {
        lock.unlock();
    }
} else {
    // Handle lock not acquired
}

这个示例中,我们使用tryLock()方法尝试获取锁,如果获取成功,则执行同步代码块。否则,我们可以处理锁未获取的情况。

公平锁和非公平锁

Lock接口提供了两种锁:公平锁和非公平锁。公平锁会按照线程请求的顺序分配锁,而非公平锁则不保证按照请求的顺序分配锁。

java

Copy

Lock fairLock = new ReentrantLock(true);
Lock nonFairLock = new ReentrantLock(false);

这个示例中,我们创建了两个锁对象,一个是公平锁,另一个是非公平锁。

注意事项

使用Lock接口时需要注意以下几点:

  • Lock接口提供了更多的功能和灵活性,但也增加了代码的复杂度和风险。
  • 如果一个线程获取了锁,但是没有及时释放锁,其他线程可能会一直等待,导致死锁等问题。
  • Lock接口不同于synchronized关键字,它不会自动释放锁,必须手动释放锁,否则可能会导致死锁等问题。
  • Lock接口不同于synchronized关键字,它支持中断等待锁的线程,可以更加灵活地处理线程的中断请求。

Semaphore类

Semaphore类是Java中另一个常见的同步机制。它可以用于控制同时访问某个资源的线程数量,从而避免资源的过度占用和竞争。

获取许可证和释放许可证

Semaphore类提供了两个方法来获取许可证和释放许可证:

  • acquire():获取一个许可证,如果没有许可证可用,则当前线程会等待,直到有许可证可用。
  • release():释放一个许可证。
Semaphore semaphore = new Semaphore(10);
semaphore.acquire();
try {
    // Synchronized code block implementation
} finally {
    semaphore.release();
}

这个示例中,我们创建了一个Semaphore对象,初始值为10,表示最多有10个线程可以同时访问某个资源。然后使用acquire()方法获取许可证,使用try-finally语句块来执行同步代码块,最后使用release()方法释放许可证。

注意事项

使用Semaphore类时需要注意以下几点:

  • Semaphore类可以用于控制同时访问某个资源的线程数量,可以避免资源的过度占用和竞争。
  • 如果一个线程获取了许可证,但是没有及时释放许可证,其他线程可能会一直等待,导致资源的浪费和性能的下降。
  • Semaphore类不同于synchronized关键

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

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

相关文章

Vivado综合属性系列之二 SRL_STYLE

目录 一、前言 二、SRL_STYLE 2.1 移位寄存器实现方式 2.2 工程代码 2.3 参考资料 一、前言 移位寄存器SRL在工程中属于使用频率较高个模块,可用于存储数据,实现串并转换; 根据数据移动方向可分为左移寄存器,右移寄存器&#x…

Vue3-黑马(八)

目录: (1)vue3-进阶-antdv-分页 (2)vue3-进阶-antdv-搜索 (3)vue3-进阶-antdv-删除1 (1)vue3-进阶-antdv-分页 分页显示不对,修改下方分页条: …

Web 自动化笔记-第一章 Selenium 环境搭建

1.自动化测试能解决什么问题? 1. 解决-回归测试 2. 解决-压力测试 3. 解决-兼容性测试 4. 提高测试效率,保证产品质量 回归测试: 项目在发新版本之后对项目之前的功能进行验证 压力测试: 可以理解多用户同时去操作软件, 统计软件服…

近1500支队伍、6000名开发者齐聚,第三届Light技术公益创造营收官

在很多老年人看来,融入数字生活并不容易,经常误点广告、不时接到诈骗电话、不会操作智能手机……但有些老年人并不担心这些,“误点了付款,有人会打电话过来,提醒我不要被骗了。”一位老人放心地进行着“网上冲浪”。而…

Python程序员该如何提高薪资水平?我来谈谈实用的五大方法

今天我要跟小伙伴们讨论的话题是:Python程序员该如何提升自己的价值?换句话说,程序员该如何逐渐增加自己的薪资?我想这是大家都关心的一个问题。首先,我们要明确一点,程序员的价值所在是什么?关…

深度学习之图像分类(一):AlexNet

本专栏介绍基于深度学习进行图像识别的经典和前沿模型,将持续更新,包括不仅限于:AlexNet, ZFNet,VGG,GoogLeNet,ResNet,DenseNet,SENet,MobileNet&#xff0c…

var、let、const和执行上下文

let/const/var let 基本语法 ES6新增了let命令,用于声明变量,其语法类似于var,但是所声明的变量只在let命令所在的代码块内有效 不存在变量提升 var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为und…

【部署jar包到服务器】

部署打好的jar包到服务器 首先需要安装对应版本的jdk 查看所有可安装的jdk版本 yum -y list java 选择对应的安装 例如 yum install -y java-1.8.0-openjdk-devel.x86_64 安装好之后,查看jdk版本 java -version 默认安装位置在 usr/lib/jvm之中 倘若你之前的版本不对…

引爆海外市场:ChatGPT带来定制化营销活动的奇迹

在定制一场海外营销活动时,需要首先了解海外市场和定制营销活动的关键是研究目标市场的文化和消费习惯。这包括但不限于: 目标市场的语言和文化背景当地消费者的购买习惯和偏好该领域的市场趋势和竞争情况目标市场的法律法规、行业标准和规范推广渠道和…

编译opencv4.7.0 + opencv_contrib 记录

最近一个项目需要涉及到图像拼接算法,网上了解一番,也大致有思路: 1. 利用surf算法查找特征点 2. 过滤掉一些,获取good点 3. 然后进行配准(图像扭曲),对接 4. 形成最终拼接图片 这些工作&a…

NeRF原理简介及实现

“ NeRF(Neural Radiance Fields)是一种先进的计算机图形学技术,能够使用深度全连接神经网络优化场景的连续5D函数表示,从而生成高度逼真的3D场景。该技术的优势在于没有使用离散化的网格或体素来表示场景,而是使用一个…

【Pandas与SQL系列】Pandas实现分布函数percent_rank、cume_dist

目录 1,分布函数,1.1,percent_rank()1.2,cume_dist()1.3 SQL例子 2,Pandas 实现3,补充Pandas实现排序 1,分布函数, 应用场景:快速查看某个记录所归属的组内的比例 分布函数分类及基础语法&…

asp.net952-sqlserver学生成绩信息管理系统开发

本学生管理系统主要学校内部提供服务,系统分为管理员,教师和学生三部分。 本研究课题重点主要包括了下面几大模块:用户登录,管理员管理,教师信息管理,学生信息管理,课程信息管理,考试信息管理,成绩信息管理系统设置等功能。这几个…

基于深度自编码网络实现轴承故障诊断

1.网络模型(数据集为CWRU) 代码实现了一个基于DAE的分类模型,用于对给定数据集进行分类。首先,通过DAE模型对原始数据进行特征提取和降维,然后使用分类模型将提取的特征与标签相匹配,以便对新数据进行分类。 代码的主要流程: 导…

用激光点云估算建筑高度【PDAL|PostgreSQL】

LiDAR 数据可以非常强大地提取城市规模的地面和物体的高程。 在 One Concern,我们正在使用 LiDAR 数据提取地面和建筑物高程,以改进进入我们的自然灾害模型的暴露信息,最终估计洪水和地震的影响。 由于 3DEP 项目预计将在 2023 年之前收集全…

STM32------GPIO

GPIO 一、介绍 1、1 什么是GPIO? 输入输出端口 1、2 GPIO特点 1、不同封装IO数量不一样。 2、快速翻转,每次翻转最快只需要两个时钟周期。 3、每个IO都可以做中断。 4、支持8种工作模式。 1、3 GPIO电气特性 STM32工作电压范围:2~3…

【C进阶】通讯录的实现(静态+动态)

目录 前言: 一.静态通讯录的实现 1.关于通讯录的前期准备 (1)菜单的打印 (2)建立一个联系人的信息 (3)通讯录整体 (4)宏定义常量 (5)主函数菜单选项的功能 2.通讯录的功能实现 (1)初始化通讯录 (2)增加指定联系人 (3) 展示通讯录 "FindByName函数" (4)删…

Autosar 规范接口之SPI

Autosar SPI 概述(Specification of SPI Handler/Driver ) 基础知识介绍 在AutoSar标准中,与SPI通讯相关的三个术语:Channel、Job和Sequence。 1个Channel对应1个发送缓冲区和1接收缓冲区;1个Job对应着1次SPI通讯发送…

(第45册)HTML5网页游戏设计从基础到开发(第2版·微课视频版)

HTML5是W3C组织近年来发布的一项引起业内轰动的Web新标准。它几乎颠覆现有Web应用, HTML5从根本上改变了开发商开发web应用的方式,从桌面浏览器到移动应用,这种语言和标准都正在影响将继续影响着各种操作平台。 本书是第2版,第1版2018年出版,经历6次印刷…

【项目开发】GoFrame+Vue项目部署到阿里云服务器

前言 本来想都用docker部署的,结果学艺实在是不精,只能先这么委曲求全宝塔页面的反向代理一直无法生效,用了重定向跳转页面宝塔的网站也可以构建go项目 背景 后端使用GoFrame框架,前端使用Vue 3 TypeScript Vite,…