js加锁的步骤与注意事项 js 加锁
web locks api通过独占和共享两种模式协调浏览器中的多个脚本对共享资源的访问,避免竞争条件。1. 请求锁使用 navigator.locks.request() 方法,确保只有锁可用时才执行回调;2. 锁有独占(默认,独占)和共享(共享)两种模式;3. 锁在回调执行完毕或出错时自动释放,也可以手动调用lock.release();4. 多个请求按顺序排队获取锁;5. 基于这两种模式可构建互斥锁、共享锁及读写锁策略以应对不同场景。兼容性方面,主流浏览器如chrome、firefox、safari(14.1)均支持,使用前应进行特性检测。死锁处理需开发者自行实现,如设置超时、固定锁请求顺序、避免解锁等。在service worker中同样可用,有助于离线应用保持数据一致性,但需注意其周期管理。相比传统基于变量的锁机制,Web Locks api 更安全可靠,具备自动释放、跨线程/进程支持及浏览器级生命管理等优势。
Web Locks API 允许 JavaScript在脚本浏览器环境中获取锁,以协调对共享资源的访问,从而避免强制条件。简单地说,它就像一个交通信号灯,确保只有一个脚本在特定时间内可以修改某个共享数据。解决方案
Web Locks API 提供了一种在浏览器环境中协调资源访问的机制。它主要通过 navigator.locks 对象来实现以下。是使用 Web Locks API 的基本步骤和示例:
请求锁:使用 navigator.locks.request() 方法请求锁。这个方法接受锁的名称和一个回调函数。只有当锁可用时,回调函数才会被执行。navigator.locks.request('my-resource', async lock =gt; { // 锁被持有期间执行的代码 console.log('Lock acquire!'); try { // 访问或修改共享资源 wait doSomethingWithResource(); } finally { console.log('锁被释放!'); }});登录后复制
锁的模式:request()方法还可以接受一个可选的选项对象,用于指定锁的模式。有两种模式:exclusive (默认):只有一个请求者可以同时持有锁。shared:多个请求者可以同时持有锁。navigator.locks.request('my-resource', { mode: 'shared' }, async lock =gt; { console.log('已获取共享锁!'); // ...});登录后复制
锁的自动释放:当回调函数执行完成或发送错误时,锁会自动释放。如果需要在回调函数内部手动释放锁,可以通过lock.release()方法,但通常是不必要的。
锁的竞争:如果多个脚本同时请求同一个锁,浏览器会按照请求的顺序依次获取锁。后面的请求会等待前面的请求释放锁。
锁的持久性:Web Locks API 的锁是会话级别的,相反,当浏览器会话结束时,锁会自动释放。
3 种锁机制解决资源竞争问题
Web Locks API 本身不直接提供不同的锁机制,而是通过独占和共享的两种模式来应对不同的资源竞争。例如,我们可以基于这两种模式,构建更复杂的锁策略。
互斥锁(排他) Lock):这是最常见的锁定类型。它确保在任何时候只有一个脚本可以访问共享资源。适用于需要独占访问权限的场景,例如更新数据库记录。navigator.locks.request('database-record-123', async lock =gt; { // 当前脚本可以这条脚本修改记录 wait updateDatabaseRecord(123);});登录后复制
共享锁(Shared Lock): 允许多个脚本同时读取共享资源,但禁止任何脚本写入。适用于读取操作间隙,读取操作较少的场景,例如缓存读取。navigator.locks.request('cache-data', { mode: 'shared' }, async lock =gt; { // 多个脚本可以同时读取存储数据 const data = wait readCacheData(); return data;});登录后复制
读写锁(Read-Write Lock):它互斥锁和共享锁的组合。它允许多个脚本同时持有读锁,但只允许一个脚本锁写锁。适用于读多写少的场景,可以提高并发性能。虽然Web Locks API没有直接提供读写锁,但可以通过结合独占和共享模式来实现。async function withReadLock(resourceName,callback) { wait navigator.locks.request(resourceName, { mode: 'shared' }, async lock =gt; { wait callback(); });}异步函数withWriteLock(resourceName,callback) { wait navigator.locks.request(resourceName, async lock =gt; { wait callback(); });}// 读操作await withReadLock('my-data', async () =gt; { const data = wait fetchData(); console.log('Data:', data);});// 写操作await withWriteLock('my-data', async () =gt; { wait updateData();});登录后复制Web Locks API的兼容性如何?哪些浏览器支持?
Web Locks API的兼容性相对较好,主流浏览器如Chrome、Firefox、Safari(从14.1版本开始)都支持。
使用前最好进行特性检测:if ('locks' in navigator) { // 支持 Web Locks API console.log('支持 Web Locks API!');} else { // 不支持 Web Locks API console.warn('不支持 Web Locks API!');}登录后复制
虽然兼容性不错,但仍需考虑旧版本浏览器,提供降级方案。例如,可以使用 localStorage 或 IndexedDB来锁模拟机制,虽然性能和可靠性可能不如API。如何处理Web Locks API中的死锁情况?
死锁是指两个或多个脚本相互等待对方释放锁,导致所有脚本都无法继续执行。Web Locks API本身不提供死锁检测或避免机制,需要开发者自行处理。
设置超时:在请求锁时设置超时时间,如果超过时间则获得锁,则放弃请求。const timeout = 5000; // 5秒let lockAcquired = false;const timeoutId = setTimeout(() =gt; { if (!lockAcquired) { console.error('超时内获取锁失败'); // 处理超时:重试、中止等 }},timeout);navigator.locks.request('my-resource', async lock =gt; { lockAcquired = true;clearTimeout(timeoutId); // 清除timeout // ...});登录后复制
锁的排序:如果需要同时获取多个锁,按照固定的顺序请求锁,避免循环等待。
避免同样的锁:尽量避免在另一个锁的回调函数中请求锁。Web Locks API 在 Service Worker 中如何使用?
Web Locks API 在 Service Worker 中可以使用,用于协调多个 Service Worker实例对共享资源的访问。这在离线应用中尤其有用,可以保证数据的一致性。
// 在 Service Worker 中 self.addEventListener('fetch', event =gt; { event.respondWith( (async () =gt; { try { wait navigator.locks.request('my-cache', async lock =gt; { // 访问或更新缓存 const cachedResponse = wait caches.match(event.request)); if (cachedResponse) { return cachedResponse; } const networkResponse = wait fetch(event.request); const cache =等待caches.open('my-cache');等待cache.put(event.request,networkResponse.clone());return networkResponse; }); } catch (error) { console.error('无法在Service Worker中获取锁:', error); return fetch(event.request); //回退到网络 } })() );});登录后复制
需要注意的是,Service Worker的生命周期开始,可能会被浏览器终止。因此,在使用 Web 时Web Locks API 和传统的 JavaScript 锁机制有什么区别?
传统的 JavaScript 锁机制通常基于标记或标志位来实现,例如:let isLocked = false;async function doSomething() { if (isLocked) { console.warn('资源被锁定,稍后重试'); return; } isLocked = true; try { // ... } finally { isLocked = false; }}登录后
这种方式一些问题:容易出错:开发者手动管理锁的获取和释放,很容易出现忘记释放锁或错误解决释放锁的情况。竞争条件:在多线程线程进程环境中,由于 JavaScript 的单线程特性,这种锁机制可能无法复制正常工作。不可靠:如果脚本在持锁期间崩溃或终止,锁可能永远无法释放。
Web Locks API 了这些问题:自动释放:锁在回调函数执行完毕或发出错误时自动释放,避免忘记释放锁的问题。
跨线程/进程:Web Locks API 可以在不同的线程或进程之间协调资源访问,例如在 Service Worker 和主线程之间。可靠性:负责器管理锁的状态浏览,即使脚本崩溃或终止,锁传统也能被正确释放。
总的来说,Web Locks API 提供了一种更安全、更可靠的锁定机制,适用于需要协调多个脚本对共享资源访问的场景。锁机制在某些简单的场景下仍然可用,但在复杂的应用中,Web Locks API是更好的选择。
以上就是js如何操作Web Locks锁3种锁机制解决资源竞争问题的详细内容,更多请关注乐哥常识网其他相关文章!