nodejs 并发执行 锁

2025-04-14 16

nodejs 并发执行 锁

在 Node.js 中处理并发任务时,可能会遇到多个异步操作同时访问共享资源的问题。为了避免数据竞争或不一致的状态,我们需要引入锁机制来控制并发。解决方案,并提供几种实现思路和代码示例。

解决方案

通过使用锁机制(如互斥锁、读写锁等),可以确保在同一时间只有一个任务能够访问共享资源。Node.js 中可以通过多种方式实现锁,例如基于 Promise 的同步锁、Redis 分布式锁、或者使用第三方库如 async-mutexredlock


1. 基于 Promise 的简单锁

最简单的锁实现是通过一个标志位来控制任务的顺序执行。以下是一个基于 Promise 的锁实现:

javascript
class SimpleLock {
  constructor() {
    this.isLocked = false;
  }</p>

<p>acquire() {
    return new Promise((resolve) => {
      const checkAndResolve = () => {
        if (!this.isLocked) {
          this.isLocked = true;
          resolve();
        } else {
          setTimeout(checkAndResolve, 10); // 每隔 10ms 检查一次锁状态
        }
      };
      checkAndResolve();
    });
  }</p>

<p>release() {
    this.isLocked = false;
  }
}</p>

<p>// 示例:模拟并发任务
const lock = new SimpleLock();</p>

<p>function task(name, delay) {
  return lock.acquire().then(() => {
    console.log(<code>${name} 开始);
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log(${name} 完成);
        lock.release();
        resolve();
      }, delay);
    });
  });
}

Promise.all([ task('Task A', 2000), task('Task B', 1000), ]).then(() => { console.log('所有任务完成'); });

说明
- acquire() 方法用于获取锁,只有当锁未被占用时才能继续执行。
- release() 方法用于释放锁,允许其他任务获取锁。


2. 使用 async-mutex 实现锁

async-mutex 是一个流行的第三方库,提供了更简洁的锁实现方式。以下是使用该库的示例:

javascript
const { Mutex } = require('async-mutex');</p>

<p>const mutex = new Mutex();</p>

<p>function task(name, delay) {
  return mutex.runExclusive(async () => {
    console.log(<code>${name} 开始);
    await new Promise((resolve) => setTimeout(resolve, delay));
    console.log(${name} 完成);
  });
}

Promise.all([ task('Task A', 2000), task('Task B', 1000), ]).then(() => { console.log('所有任务完成'); });

说明
- runExclusive() 方法会自动确保同一时间只有一个任务执行。
- 当前任务完成后,锁会自动释放。


3. Redis 分布式锁

在分布式系统中,多个进程可能需要协调对共享资源的访问。此时可以使用 Redis 实现分布式锁。以下是一个基于 redlock 库的示例:

javascript
const Redlock = require('redlock');
const redis = require('redis');</p>

<p>// 创建 Redis 客户端
const client = redis.createClient({
  host: 'localhost',
  port: 6379,
});</p>

<p>// 初始化 Redlock
const redlock = new Redlock([client], {
  driftFactor: 0.01, // 锁过期时间的漂移因子
  retryCount: 10,    // 尝试获取锁的次数
  retryDelay: 200,   // 每次尝试之间的延迟
});</p>

<p>async function task(name, delay) {
  const lockKey = 'shared<em>resource</em>lock';
  const lock = await redlock.lock(lockKey, 5000); // 锁定 5 秒</p>

<p>try {
    console.log(<code>${name} 开始);
    await new Promise((resolve) => setTimeout(resolve, delay));
    console.log(${name} 完成);
  } finally {
    await lock.unlock(); // 释放锁
  }
}

Promise.all([ task('Task A', 2000), task('Task B', 1000), ]).then(() => { console.log('所有任务完成'); });

说明
- redlock.lock() 方法用于获取分布式锁。
- 锁的过期时间应根据任务执行时间合理设置,避免死锁。


4. 其他思路:队列机制

除了锁机制,还可以通过队列的方式控制任务的并发执行。以下是一个基于队列的实现:

javascript
class TaskQueue {
  constructor() {
    this.queue = [];
    this.isProcessing = false;
  }</p>

<p>addTask(task) {
    this.queue.push(task);
    this.processNext();
  }</p>

<p>async processNext() {
    if (this.isProcessing || this.queue.length === 0) return;</p>

<pre><code>this.isProcessing = true;
const task = this.queue.shift();
try {
  await task();
} finally {
  this.isProcessing = false;
  this.processNext();
}

}
}

const queue = new TaskQueue();

function createTask(name, delay) {
return async () => {
console.log(${name} 开始);
await new Promise((resolve) => setTimeout(resolve, delay));
console.log(${name} 完成);
};
}

queue.addTask(createTask('Task A', 2000));
queue.addTask(createTask('Task B', 1000));

setTimeout(() => {
console.log('所有任务完成');
}, 3000);

说明
- 队列机制可以确保任务按顺序执行,避免并发问题。
- 适用于不需要复杂锁逻辑的场景。


几种在 Node.js 中实现并发控制的思路和代码示例:
1. 基于 Promise 的简单锁:适合单机环境下的轻量级任务。
2. 使用 async-mutex:提供了更简洁的 API 和更好的可维护性。
3. Redis 分布式锁:适用于分布式系统中的共享资源访问控制。
4. 队列机制:通过任务排队的方式避免并发冲突。

根据实际需求选择合适的方案,可以有效解决并发问题并提高系统的稳定性。

Image

1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!cheeksyu@vip.qq.com
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或教程,您可以投稿发布,成功分享后有积分奖励和额外收入!
5.严禁将资源用于任何违法犯罪行为,不得违反国家法律,否则责任自负,一切法律责任与本站无关

源码下载