0

0

js如何操作Web Locks锁 3种锁机制解决资源竞争问题

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-06-22 13:36:02

|

322人浏览过

|

来源于php中文网

原创

web locks api 通过 exclusive 和 shared 两种模式协调浏览器中多个脚本对共享资源的访问,避免竞争条件。1. 请求锁使用 navigator.locks.request() 方法,确保只有锁可用时才执行回调;2. 锁有 exclusive(默认,独占)和 shared(共享)两种模式;3. 锁在回调执行完毕或出错时自动释放,也可手动调用 lock.release();4. 多个请求按顺序排队获取锁;5. 锁为会话级别,浏览器关闭时释放。基于这两种模式可构建互斥锁、共享锁及读写锁策略以应对不同场景。兼容性方面,主流浏览器如 chrome、firefox、safari(14.1+)均支持,使用前应进行特性检测。死锁处理需开发者自行实现,如设置超时、固定锁请求顺序、避免嵌套锁等。在 service worker 中同样可用,有助于离线应用保持数据一致性,但需注意其生命周期管理。相比传统基于变量的锁机制,web locks api 更安全可靠,具备自动释放、跨线程/进程支持及浏览器级管理等优势。

js如何操作Web Locks锁 3种锁机制解决资源竞争问题

Web Locks API 允许 JavaScript 脚本在浏览器环境中获取锁,以协调对共享资源的访问,从而避免竞争条件。简单来说,它就像一个交通信号灯,确保只有一个脚本在特定时间内可以修改某个共享数据。

js如何操作Web Locks锁 3种锁机制解决资源竞争问题

解决方案

Web Locks API 提供了一种在浏览器环境中协调资源访问的机制。它主要通过 navigator.locks 对象来实现。以下是使用 Web Locks API 的基本步骤和示例:

js如何操作Web Locks锁 3种锁机制解决资源竞争问题
  1. 请求锁: 使用 navigator.locks.request() 方法请求锁。这个方法接受锁的名称和一个回调函数。只有当锁可用时,回调函数才会被执行。

    js如何操作Web Locks锁 3种锁机制解决资源竞争问题
    navigator.locks.request('my-resource', async lock => {
      // 锁被持有期间执行的代码
      console.log('Lock acquired!');
      try {
        // 访问或修改共享资源
        await doSomethingWithResource();
      } finally {
        console.log('Lock released!');
      }
    });
  2. 锁的模式: request() 方法还可以接受一个可选的选项对象,用于指定锁的模式。有两种模式:

    • exclusive (默认): 只有请求者可以持有锁。
    • shared: 多个请求者可以同时持有锁。
    navigator.locks.request('my-resource', { mode: 'shared' }, async lock => {
      console.log('Shared lock acquired!');
      // ...
    });
  3. 锁的自动释放: 当回调函数执行完毕或抛出错误时,锁会自动释放。如果需要在回调函数内部手动释放锁,可以通过 lock.release() 方法,但这通常是不必要的。

  4. 锁的竞争: 如果多个脚本同时请求同一个锁,浏览器会按照请求的顺序依次授予锁。后面的请求会等待前面的请求释放锁。

  5. 锁的持久性: Web Locks API 的锁是会话级别的,也就是说,当浏览器会话结束时,锁会自动释放。

3 种锁机制解决资源竞争问题

Web Locks API 本身不直接提供三种不同的锁机制,而是通过 exclusiveshared 两种模式来应对不同的资源竞争场景。我们可以基于这两种模式,构建更复杂的锁策略。

  1. 互斥锁 (Exclusive Lock): 这是最常见的锁类型。它确保在任何时候只有一个脚本可以访问共享资源。适用于需要独占访问权限的场景,例如更新数据库记录。

    navigator.locks.request('database-record-123', async lock => {
      // 只有当前脚本可以修改这条记录
      await updateDatabaseRecord(123);
    });
  2. 共享锁 (Shared Lock): 允许多个脚本同时读取共享资源,但阻止任何脚本写入。适用于读取操作频繁,写入操作较少的场景,例如缓存读取。

    navigator.locks.request('cache-data', { mode: 'shared' }, async lock => {
      // 多个脚本可以同时读取缓存数据
      const data = await readCacheData();
      return data;
    });
  3. 读写锁 (Read-Write Lock): 这是互斥锁和共享锁的组合。它允许多个脚本同时持有读锁,但只允许一个脚本持有写锁。适用于读多写少的场景,可以提高并发性能。虽然 Web Locks API 没有直接提供读写锁,但可以通过结合 exclusiveshared 模式来实现。

    Magic AI Avatars
    Magic AI Avatars

    神奇的AI头像,获得200多个由AI制作的自定义头像。

    下载
    async function withReadLock(resourceName, callback) {
      await navigator.locks.request(resourceName, { mode: 'shared' }, async lock => {
        await callback();
      });
    }
    
    async function withWriteLock(resourceName, callback) {
      await navigator.locks.request(resourceName, async lock => {
        await callback();
      });
    }
    
    // 读操作
    await withReadLock('my-data', async () => {
      const data = await fetchData();
      console.log('Data:', data);
    });
    
    // 写操作
    await withWriteLock('my-data', async () => {
      await updateData();
    });

Web Locks API 的兼容性如何?哪些浏览器支持?

Web Locks API 的兼容性相对较好,主流浏览器如 Chrome, Firefox, Safari (从 14.1 版本开始) 都支持。使用前最好进行特性检测:

if ('locks' in navigator) {
  // Web Locks API is supported
  console.log('Web Locks API is supported!');
} else {
  // Web Locks API is not supported
  console.warn('Web Locks API is not supported!');
}

虽然兼容性不错,但仍需考虑旧版本浏览器,提供降级方案。例如,可以使用 localStorageIndexedDB 来模拟锁机制,虽然性能和可靠性可能不如原生 API。

如何处理 Web Locks API 中的死锁情况?

死锁是指两个或多个脚本相互等待对方释放锁,导致所有脚本都无法继续执行。Web Locks API 本身不提供死锁检测或避免机制,需要开发者自行处理。

  • 设置超时: 在请求锁时设置超时时间,如果超过时间仍未获得锁,则放弃请求。

    const timeout = 5000; // 5 seconds
    let lockAcquired = false;
    
    const timeoutId = setTimeout(() => {
      if (!lockAcquired) {
        console.error('Failed to acquire lock within timeout');
        // Handle timeout: retry, abort, etc.
      }
    }, timeout);
    
    navigator.locks.request('my-resource', async lock => {
      lockAcquired = true;
      clearTimeout(timeoutId); // Clear the timeout
    
      // ...
    });
  • 锁的排序: 如果需要同时获取多个锁,按照固定的顺序请求锁,避免循环等待。

  • 避免嵌套锁: 尽量避免在一个锁的回调函数中请求另一个锁。

Web Locks API 在 Service Worker 中如何使用?

Web Locks API 在 Service Worker 中同样可以使用,用于协调多个 Service Worker 实例对共享资源的访问。这在离线应用中尤其有用,可以确保数据的一致性。

// In Service Worker
self.addEventListener('fetch', event => {
  event.respondWith(
    (async () => {
      try {
        await navigator.locks.request('my-cache', async lock => {
          // Access or update cache
          const cachedResponse = await caches.match(event.request);
          if (cachedResponse) {
            return cachedResponse;
          }

          const networkResponse = await fetch(event.request);
          const cache = await caches.open('my-cache');
          await cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
      } catch (error) {
        console.error('Failed to acquire lock in Service Worker:', error);
        return fetch(event.request); // Fallback to network
      }
    })()
  );
});

需要注意的是,Service Worker 的生命周期较短,可能会被浏览器随时终止。因此,在使用 Web Locks API 时,要确保锁的释放逻辑能够可靠执行,避免资源长期被锁定。

Web Locks API 和传统的 JavaScript 锁机制有什么区别?

传统的 JavaScript 锁机制通常基于变量或标志位来实现,例如:

let isLocked = false;

async function doSomething() {
  if (isLocked) {
    console.warn('Resource is locked, try again later');
    return;
  }

  isLocked = true;
  try {
    // ...
  } finally {
    isLocked = false;
  }
}

这种方式存在一些问题:

  • 容易出错: 开发者需要手动管理锁的获取和释放,容易出现忘记释放锁或错误释放锁的情况。
  • 竞争条件: 在多线程或多进程环境中,由于 JavaScript 的单线程特性,这种锁机制可能无法正常工作。
  • 不可靠: 如果脚本在持有锁期间崩溃或终止,锁可能永远无法释放。

Web Locks API 解决了这些问题:

  • 自动释放: 锁在回调函数执行完毕或抛出错误时自动释放,避免忘记释放锁的问题。
  • 跨线程/进程: Web Locks API 可以在不同的线程或进程之间协调资源访问,例如在 Service Worker 和主线程之间。
  • 可靠性: 浏览器负责管理锁的状态,即使脚本崩溃或终止,锁也能被正确释放。

总的来说,Web Locks API 提供了一种更安全、更可靠的锁机制,适用于需要协调多个脚本对共享资源访问的场景。虽然传统的 JavaScript 锁机制在某些简单场景下仍然可用,但在复杂的应用中,Web Locks API 是更好的选择。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

1058

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

839

2023.11.06

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

32

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

29

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

103

2026.02.06

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何进行WebSocket调试
如何进行WebSocket调试

共1课时 | 0.1万人学习

TypeScript全面解读课程
TypeScript全面解读课程

共26课时 | 5.1万人学习

前端工程化(ES6模块化和webpack打包)
前端工程化(ES6模块化和webpack打包)

共24课时 | 5.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号