当前位置: 首页 > news >正文

在分布式场景下可以使用synchronized加锁么?

        首先说结论,在分布式系统中,单纯使用 Java 中的 synchronized 关键字是无法满足需求的,下面从 synchronized 的作用原理、在分布式场景下的局限性以及替代方案等方面详细分析。

一、synchronized 的作用原理

        在 Java 中,synchronized 关键字用于实现线程同步,它可以保证在同一时刻,只有一个线程能够访问被 synchronized 修饰的代码块或方法。其本质是通过获取对象的监视器(monitor)来实现互斥访问,这是基于 JVM 层面的同步机制,作用范围仅限于单个 JVM 进程内。

        以下是一个简单的 synchronized 使用示例:

public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}public static void main(String[] args) throws InterruptedException {SynchronizedExample example = new SynchronizedExample();Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});t1.start();t2.start();t1.join();t2.join();System.out.println("Count: " + example.count);}
}

        在这个示例中,increment 方法被 synchronized 修饰,确保了在同一时刻只有一个线程能够执行该方法,从而避免了多线程环境下的竞态条件。

二、在分布式场景下的局限性

        分布式系统由多个独立的 JVM 进程组成,不同进程之间无法直接共享对象的监视器。synchronized 只能保证单个 JVM 内的线程同步,无法实现跨 JVM 进程的同步。因此,在分布式系统中,如果多个进程同时访问共享资源,使用 synchronized 无法保证资源的互斥访问,可能会导致数据不一致等问题。

三、分布式系统中的替代方案

        为了实现分布式环境下的同步,可以使用以下几种常见的方案:

        1.数据库锁

        可以利用数据库的行级锁或表级锁来实现分布式锁。例如,在 MySQL 中,可以使用 SELECT ... FOR UPDATE 语句来获取行级锁。

-- 获取行级锁
SELECT * FROM distributed_lock_table WHERE lock_name = 'resource_lock' FOR UPDATE;

        这种方式的优点是实现简单,不需要额外的组件;缺点是性能较差,对数据库的依赖较大。

        2.Redis 分布式锁——SETNX

        Redis 是一个高性能的键值存储系统,可以利用 Redis 的原子操作来实现分布式锁。常见的实现方式是使用 SETNX(SET if Not eXists)命令。

import redis.clients.jedis.Jedis;public class RedisDistributedLock {private static final String LOCK_KEY = "distributed_lock";private static final String LOCK_VALUE = "lock_value";private static final int EXPIRE_TIME = 1000; // 锁的过期时间,单位:毫秒public static boolean acquireLock(Jedis jedis) {String result = jedis.set(LOCK_KEY, LOCK_VALUE, "NX", "PX", EXPIRE_TIME);return "OK".equals(result);}public static void releaseLock(Jedis jedis) {jedis.del(LOCK_KEY);}public static void main(String[] args) {Jedis jedis = new Jedis("localhost", 6379);if (acquireLock(jedis)) {try {// 执行临界区代码System.out.println("获取到锁,执行临界区代码");} finally {releaseLock(jedis);}} else {System.out.println("未获取到锁");}jedis.close();}
}

        这种方式的优点是性能高,实现相对简单;缺点是需要额外的 Redis 服务,并且需要处理锁的过期时间和异常情况。

        3.Redis 分布式锁——TryLock

        事实上,Redis 实现 TryLock 也要依靠 SET 命令的原子性,通过设置特定的键值对以及过期时间来模拟锁的获取和释放。当执行 SET 命令时,如果键不存在则设置成功,相当于获取到锁;若键已存在则设置失败,代表锁已被其他客户端持有。

       以下是使用 Jedis实现 tryLock 功能的示例代码:

import redis.clients.jedis.Jedis;public class RedisTryLockExample {private static final String LOCK_KEY = "distributed_lock";private static final String LOCK_VALUE = "lock_value";private static final int EXPIRE_TIME = 10000; // 锁的过期时间,单位:毫秒private Jedis jedis;public RedisTryLockExample() {this.jedis = new Jedis("localhost", 6379);}/*** 尝试获取锁* @return 如果获取到锁返回 true,否则返回 false*/public boolean tryLock() {// 使用 SET 命令的 NX(Not eXists)和 PX(过期时间)选项String result = jedis.set(LOCK_KEY, LOCK_VALUE, "NX", "PX", EXPIRE_TIME);return "OK".equals(result);}/*** 释放锁*/public void unlock() {jedis.del(LOCK_KEY);}public static void main(String[] args) {RedisTryLockExample lockExample = new RedisTryLockExample();if (lockExample.tryLock()) {try {// 模拟执行临界区代码System.out.println("获取到锁,执行临界区代码");Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();} finally {lockExample.unlock();System.out.println("释放锁");}} else {System.out.println("未获取到锁");}lockExample.jedis.close();}
}

        比较SETNX和TryLock:

        SETNX 的问题:使用 SETNX 命令设置锁时,无法原子性地设置锁的过期时间。若在设置完锁之后,在设置过期时间之前,客户端发生异常崩溃,就会导致锁无法释放,造成死锁。SETNX只是单纯地判断键是否存在并进行设置,对于锁的过期时间等额外属性需要额外的命令来处理,在实现分布式锁时需要编写更多的代码来保证正确性,代码的可读性和可维护性较差。功能相对单一,仅能实现键的存在性判断和设置操作。

        TryLock 实现的优势:使用 SET 命令并结合 NX 和 PX/EX 选项可以原子性地完成锁的设置和过期时间的设置,避免了上述死锁问题。从功能语义上来说,TryLock 更符合锁的使用习惯,调用者可以直观地理解其作用是尝试获取锁,并且能够方便地结合过期时间等参数进行使用,代码逻辑更加清晰。TryLock基于 SET 命令可以利用 Redis 提供的更多特性,例如可以设置不同的过期时间单位(PX 表示毫秒,EX 表示秒),还可以结合其他命令实现更复杂的分布式锁逻辑,如可重入锁等。

四、总结

        综上所述,在分布式系统中不能直接使用 synchronized 来实现同步,需要根据具体的业务场景选择合适的分布式锁方案。

相关文章:

在分布式场景下可以使用synchronized加锁么?

首先说结论&#xff0c;在分布式系统中&#xff0c;单纯使用 Java 中的 synchronized 关键字是无法满足需求的&#xff0c;下面从 synchronized 的作用原理、在分布式场景下的局限性以及替代方案等方面详细分析。 一、synchronized 的作用原理 在 Java 中&#xff0c;synchron…...

LeetCodehot 力扣热题100 从前序与中序遍历序列构造二叉树

初始版本 这段代码实现了根据前序遍历和中序遍历重建二叉树。下面我将详细解释每一行的作用&#xff0c;并逐步讲解算法的思路和运行步骤。 代码及注释 class Solution {public:// buildTree 函数用来根据前序遍历(pre)和中序遍历(in)重建二叉树TreeNode* buildTree(vector<…...

Day45(补)【软考】2022年下半年软考软件设计师综合知识真题-计算机软件知识1

文章目录 2022年下半年软考软件设计师综合知识真题第1章 计算机系统基础知识(12/38)计算机软件知识1-6/6哲学概念及收敛思维&#xff1a;是Python程序语言中&#xff0c;处理异常的结构集合&#xff0c;和这个集合之外的结构的区分&#xff0c;考Python集合之外的结构 哲学概念…...

luoguP8764 [蓝桥杯 2021 国 BC] 二进制问题

luogu题目传送门 题目描述 小蓝最近在学习二进制。他想知道 1 到 N 中有多少个数满足其二进制表示中恰好有 K 个 1。你能帮助他吗? 输入格式 输入一行包含两个整数 N 和 K。 输出格式 输出一个整数表示答案。 输入输出样例 输入 #1 7 2 输出 #1 3 说明/提示 对于…...

图形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan简介

1.Skia —— 2D 图形库 Skia 是一个 2D 图形库&#xff0c;它的作用是为开发者提供一个高层次的绘图接口&#xff0c;方便他们进行 2D 图形渲染&#xff08;比如绘制文本、形状、图像等&#xff09;。Skia 本身不直接管理 GPU 或进行底层的渲染工作&#xff0c;而是通过 底层图…...

浏览器打开Axure RP模型

1&#xff0c;直接使用chrome打开&#xff0c;提示下载插件 2&#xff0c;需要做一些操作 打开原型文件&#xff0c;找到resources\chrome\axure-chrome-extension.crx文件&#xff0c;这就是我们需要的Chrome插件。 将axure-chrome-extension.crx文件后缀名改为axure-chrome…...

【计算机网络】数据链路层数据帧(Frame)格式

在计算机网络中&#xff0c;数据帧&#xff08;Frame&#xff09; 是数据链路层的协议数据单元&#xff08;PDU&#xff09;&#xff0c;用于在物理介质上传输数据。数据帧的格式取决于具体的链路层协议&#xff08;如以太网、PPP、HDLC 等&#xff09;。以下是常见数据帧格式的…...

平面与平面相交算法杂谈

1.前言 空间平面方程&#xff1a; 空间两平面如果不平行&#xff0c;那么一定相交于一条空间直线&#xff0c; 空间平面求交有多种方法&#xff0c;本文进行相关讨论。 2.讨论 可以联立方程组求解&#xff0c;共有3个变量&#xff0c;2个方程&#xff0c;而所求直线有1个变量…...

web集群(LVS-DR)

LVS是Linux Virtual Server的简称&#xff0c;也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项 目&#xff0c;它的官方站点是 www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分&#xff0c;在 Linux2.4内核以前&#xff0c;使用LVS时必须要重新编…...

更高效实用 vscode 的常用设置

VSCode 可以说是文本编辑神器, 不止程序员使用, 普通人用其作为文本编辑工具, 更是效率翻倍. 这里分享博主对于 VSCode 的好用设置, 让 VSCode 如虎添翼 进入设置 首先进入设置界面, 后续都在这里进行配置修改 具体设置 每项配置通过搜索关键字, 来快速定位配置项 自动保存…...

win11 终端乱码导致IDE 各种输出也乱码

因为 win11 终端乱码导致IDE 各种输出也乱码导致作者对此十分头大。所以研究了各种方法。 单独设置终端编码对 HKEY_CURRENT_USER\Console 注册表进行修改对 HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processo 注册表进行修改使用命令[Console]::OutputEncoding [Syst…...

对于简单的HTML、CSS、JavaScript前端,我们可以通过几种方式连接后端

1. 使用Fetch API发送HTTP请求&#xff08;最简单的方式&#xff09;&#xff1a; //home.html // 示例&#xff1a;提交表单数据到后端 const submitForm async (formData) > {try {const response await fetch(http://your-backend-url/api/submit, {method: POST,head…...

Flutter中 List列表中移除特定元素

在 Dart 语言里&#xff0c;若要从子列表中移除特定元素&#xff0c;可以使用以下几种方法&#xff0c;下面为你详细介绍&#xff1a; 方法一&#xff1a;使用 where 方法创建新列表 where 方法会根据指定的条件筛选元素&#xff0c;然后通过 toList 方法将筛选结果转换为新列…...

DeepSeek从入门到精通(清华大学)

​ DeepSeek是一款融合自然语言处理与深度学习技术的全能型AI助手&#xff0c;具备知识问答、数据分析、编程辅助、创意生成等多项核心能力。作为多模态智能系统&#xff0c;它不仅支持文本交互&#xff0c;还可处理文件、图像、代码等多种格式输入&#xff0c;其知识库更新至2…...

动态规划:解决复杂问题的高效策略

动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种在数学、管理科学、经济学、计算机科学等领域中广泛使用的算法设计技术。它通过将复杂问题分解为更简单的子问题&#xff0c;并通过存储子问题的解来避免重复计算&#xff0c;从而高效地解决问题…...

【kafka系列】Kafka事务的实现原理

目录 1. 事务核心组件 1.1 幂等性生产者&#xff08;Idempotent Producer&#xff09; 1.2 事务协调器&#xff08;TransactionCoordinator&#xff09; 1.3 事务日志&#xff08;Transaction Log&#xff09; 2. 事务执行流程 2.1 事务初始化 2.2 发送消息 2.3 事务提…...

网络将内网服务转换到公网上

当然&#xff0c;以下是根据您提供的描述&#xff0c;对内网端口在公网上转换过程的详细步骤&#xff0c;并附上具体例子进行说明&#xff1a; 内网端口在公网上的转换过程详细步骤 1. 内网服务配置 步骤说明&#xff1a; 在内网中的某台计算机&#xff08;我们称之为“内网…...

c#自动更新-源码

软件维护与升级 修复漏洞和缺陷&#xff1a;软件在使用过程中可能会发现各种漏洞和缺陷&#xff0c;自动更新可以及时推送修复程序&#xff0c;增强软件的稳定性和安全性&#xff0c;避免因漏洞被利用而导致数据泄露、系统崩溃等问题。提升性能&#xff1a;通过自动更新&#x…...

爬虫实战:利用代理ip爬取推特网站数据

引言 亮数据-网络IP代理及全网数据一站式服务商屡获殊荣的代理网络、强大的数据挖掘工具和现成可用的数据集。亮数据&#xff1a;网络数据平台领航者https://www.bright.cn/?promoRESIYEAR50/?utm_sourcebrand&utm_campaignbrnd-mkt_cn_csdn_yingjie202502 在跨境电商、社…...

git使用,注意空格

第一节 安装完成后&#xff0c;找个目录用于存储,打开目录右击选择git bash here 命令1 姓名 回车 git config --global user.name "li" 命令2 邮箱 回车 git config --global user.email "888163.com" 命令3 初始化新仓库&#xff0c;下载克隆 回…...

从玩具舵机到视觉追踪:聊聊OpenMV色块识别背后的图像处理与坐标转换

从玩具舵机到视觉追踪&#xff1a;OpenMV色块识别背后的图像处理与坐标转换 在嵌入式视觉系统中&#xff0c;色块追踪是一个看似简单却蕴含丰富技术细节的经典问题。当我们将OpenMV摄像头对准一个彩色物体时&#xff0c;屏幕上实时跳动的矩形框背后&#xff0c;是一系列精密的图…...

XHS-Downloader终极指南:3种高效模式实现小红书内容批量采集与下载

XHS-Downloader终极指南&#xff1a;3种高效模式实现小红书内容批量采集与下载 【免费下载链接】XHS-Downloader 小红书&#xff08;XiaoHongShu、RedNote&#xff09;链接提取/作品采集工具&#xff1a;提取账号发布、收藏、点赞、专辑作品链接&#xff1b;提取搜索结果作品、…...

Apple MLX框架下的脉冲神经网络(SNN)实现与优化

1. 项目概述&#xff1a;mlx-snn的诞生背景与核心价值在深度学习领域&#xff0c;脉冲神经网络&#xff08;SNN&#xff09;正逐渐成为继传统人工神经网络&#xff08;ANN&#xff09;和卷积神经网络&#xff08;CNN&#xff09;之后的"第三代神经网络"。与常规神经网…...

高德顺风车xck、an参数逆向

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包 内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;侵权通过头像私信或名字简介叫我删除博…...

Silk v3解码器:3分钟解决微信QQ音频格式转换难题

Silk v3解码器&#xff1a;3分钟解决微信QQ音频格式转换难题 【免费下载链接】silk-v3-decoder [Skype Silk Codec SDK]Decode silk v3 audio files (like wechat amr, aud files, qq slk files) and convert to other format (like mp3). Batch conversion support. 项目地址…...

终极容器镜像管理指南:掌握ImagesCommand的完整操作教程

终极容器镜像管理指南&#xff1a;掌握ImagesCommand的完整操作教程 【免费下载链接】container A tool for creating and running Linux containers using lightweight virtual machines on a Mac. It is written in Swift, and optimized for Apple silicon. 项目地址: ht…...

ARM Trace Analyzer:指令追踪与调试核心技术解析

1. ARM Trace Analyzer技术概览指令追踪技术是现代处理器调试与性能分析的基石&#xff0c;而ARM Trace Analyzer作为CoreSight调试架构的核心组件&#xff0c;其设计哲学体现了硬件级调试的前沿思想。想象一下&#xff0c;当处理器以GHz频率运行时&#xff0c;工程师需要在不影…...

基于向量数据库与语义检索的AI记忆增强工具Memok-AI深度解析

1. 项目概述&#xff1a;一个面向记忆增强的AI工具最近在GitHub上闲逛&#xff0c;发现了一个挺有意思的项目&#xff0c;叫galaxy8691/memok-ai。乍一看这个名字&#xff0c;memok很容易让人联想到 “Memory” 和 “OK” 的组合&#xff0c;直译过来就是“记忆没问题”。点进去…...

开发者与测试者的认知偏差:为什么他们总说“这不可能重现”

一、认知偏差的根源&#xff1a;不同的工作视角与目标在软件研发的闭环中&#xff0c;开发者与测试者如同站在同一座山的两面&#xff0c;虽望向同一个产品&#xff0c;却因职责分工形成了截然不同的认知坐标系。开发者的核心目标是“构建”&#xff0c;他们沉浸于代码的逻辑编…...

如何集成OpenClaw?2026年阿里云及Coding Plan配置保姆级攻略

如何集成OpenClaw&#xff1f;2026年阿里云及Coding Plan配置保姆级攻略。OpenClaw作为阿里云生态下新一代的开源AI自动化代理平台&#xff0c;曾用名Moltbot/Clawdbot&#xff0c;凭借“自然语言交互自动化任务执行大模型智能决策”的核心能力&#xff0c;正在重构个人与企业的…...