JS篇-关于javascript、ts互斥锁的作用和写法

news/2025/3/6 23:52:37/

一、一般情况下的单线程

JavaScript 在webworks和 Node.js 环境下,主线程通常是单线程执行的,这意味着同一时间只会执行一个任务,所以大部分情况下不需要传统意义上的互斥锁。

javascript">let counter = 0;function increment() {counter++;console.log(counter);
}function decrement() {counter--;console.log(counter);
}increment();
decrement();

在这个例子中,由于代码是按顺序依次执行的,不会出现多个任务同时修改 counter 变量的情况,所以不需要互斥锁来保证数据的一致性。

二、多线程

Web Workers 允许在浏览器中创建多个线程,这些线程可以并行执行 JavaScript 代码。当多个 Web Worker 同时访问和修改共享资源时,就需要互斥锁来避免数据竞争。

javascript">// main.js
const worker = new Worker('worker.js');
let sharedResource = 0;
let lock = false;function acquireLock() {while (lock) {// 等待锁释放}lock = true;
}function releaseLock() {lock = false;
}worker.onmessage = function (event) {acquireLock();sharedResource += event.data;console.log('Shared resource:', sharedResource);releaseLock();
};worker.postMessage(1);// worker.js
self.onmessage = function (event) {self.postMessage(2);
};

在这个示例中,acquireLock 和 releaseLock 函数模拟了互斥锁的功能,确保在一个线程访问 sharedResource 时,其他线程不能同时访问。

三、 Node.js 中的多进程或异步操作

在 Node.js 中,虽然主线程是单线程的,但可以使用 child_process 模块创建多个进程,或者使用异步操作处理并发任务。当多个进程或异步操作同时访问共享资源时,也需要互斥锁来保证数据的一致性。

javascript">const fs = require('fs');
const path = require('path');const lockFilePath = path.join(__dirname, 'lockfile');function acquireLock(callback) {fs.writeFile(lockFilePath, '', { flag: 'wx' }, (err) => {if (err) {if (err.code === 'EEXIST') {// 锁已被占用,等待一段时间后重试setTimeout(() => acquireLock(callback), 100);} else {callback(err);}} else {callback(null);}});
}function releaseLock(callback) {fs.unlink(lockFilePath, callback);
}acquireLock((err) => {if (err) {console.error('Failed to acquire lock:', err);return;}// 执行需要互斥访问的操作console.log('Lock acquired, performing operation...');releaseLock((err) => {if (err) {console.error('Failed to release lock:', err);} else {console.log('Lock released.');}});
});

在这个 Node.js 示例中,通过文件锁的方式实现了互斥锁的功能,确保同一时间只有一个进程可以执行需要互斥访问的操作。

综上所述,虽然 JavaScript 主线程是单线程的,但在多线程或异步并发场景下,为了保证数据的一致性和操作的正确性,可能需要使用互斥锁。

四、TS的互斥锁

1、简单写法

javascript">class Mutex {private isLocked: boolean = false;// 尝试获取锁,如果锁已被占用则等待async acquire(): Promise<void> {while (this.isLocked) {await new Promise(resolve => setTimeout(resolve, 10));}this.isLocked = true;}// 释放锁release(): void {this.isLocked = false;}
}// 使用示例
async function main() {const mutex = new Mutex();async function task(id: number) {await mutex.acquire();console.log(`Task ${id} acquired the lock`);// 模拟一些耗时操作await new Promise(resolve => setTimeout(resolve, 1000));console.log(`Task ${id} released the lock`);mutex.release();}// 同时启动多个任务Promise.all([task(1), task(2)]);
}main();

2、高阶写法:

javascript">/*** 互斥锁函数:确保前一个调用完成后才能接受新的调用* @param func 要被锁定的函数(支持同步 & 异步)* @returns 经过锁保护的函数*/export function mutexLock<T extends (...args: any[]) => any>(func: T
): (...funcArgs: Parameters<T>) => Promise<ReturnType<T> | void> {let isLocked = false;return async function (this: any,...args: Parameters<T>): Promise<ReturnType<T> | void> {if (isLocked) return; // 🚫 忽略请求(上一个仍在执行)isLocked = true; // 🔒 进行加锁try {return await func.apply(this, args); // ⏳ 执行原始函数} finally {isLocked = false; // 🔓 任务完成,解锁}};
}


http://www.ppmy.cn/news/1577210.html

相关文章

AJAX 文件上传进度条 JAVA

JSP文件 <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8"%> <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>AJAX 文件上传进度条</title>…

OpenMCU(一):STM32F407 FreeRTOS移植

概述 本文主要描述了STM32F407移植FreeRTOS的简要步骤。移植描述过程中&#xff0c;忽略了Keil软件的部分使用技巧。默认读者熟练使用Keil软件。本文的描述是基于OpenMCU_FreeRTOS这个工程&#xff0c;该工程已经下载放好了移植stm32f407 FreeRTOS的所有文件 OpenMCU_FreeRTOS工…

vue3中Element-plus table 反选 禁用实战

在 Vue 3 中使用 Element Plus 的 el-table 组件实现反选和禁用某些行的功能&#xff0c;可以通过以下步骤实现&#xff1a; 1. 安装 Element Plus 首先&#xff0c;确保你已经安装了 Element Plus&#xff1a; npm install element-plus2. 引入 Element Plus 组件 在你的 …

MySQL创建外键失败

问题描述 我有两张表&#xff0c;它们的结构分别是&#xff1a; contens表&#xff1a; content_version表&#xff1a; 其中&#xff0c;content_version表字段content_id想要创建content表的外键 但是&#xff1a; 明明两个字段的类型、长度、是否为空都设置的一模一样&am…

H20半精度推理报错:Floating point exception (core dumped)

Nvidia H20 显卡在执行bf16&#xff0c;f16推理时程序异常中断 时间是 2025年3月4日 课题组新到的8卡H20服务器在使用过程中&#xff0c;torch加载模型进行bf16的推理时&#xff0c;出现Floating point exception (core dumped)错误 当时一头雾水&#xff0c;后来苦苦寻找&…

DApp开发从入门到精通:以太坊/Solana公链生态实战解析

在区块链技术的推动下&#xff0c;去中心化应用&#xff08;DApp&#xff09;逐渐摆脱传统中心化后台的依赖&#xff0c;转向以智能合约为核心的全合约化开发模式。这种模式通过区块链网络的分布式特性&#xff0c;实现了数据存储、业务逻辑与用户交互的完全去中心化。 一、全合…

力扣-动态规划-516 最长回文子序列

思路 dp数组定义&#xff1a;[i, j]的字符串的最长回文子序列长度为dp[i][j]递推公式&#xff1a;相等时&#xff0c;子序列2 || ij时赋值1&#xff1b; 不相等时&#xff0c;两个去掉首、去掉尾取最长dp数组初始化&#xff1a;都为0遍历顺序&#xff1a;从下往上&#xff0c;…

【第16节】C++设计模式(行为模式)-Observer(观察者)模式

一、问题背景 观察者模式&#xff08;Observer Pattern&#xff09;是应用最广泛的设计模式之一&#xff0c;尤其是在实现 **Model/View/Controller (MVC)** 架构时&#xff0c;观察者模式起到了核心作用。MVC 架构通过将业务逻辑&#xff08;Model&#xff09;、用户界面&…