建网站好,产品推广策划,中律之窗网站建设,印刷个性化网站建设的意义文章目录 前言一、异步互斥锁的作用是什么#xff1f;示例一、创建和销毁 二、如何实现#xff1f;1、标识#xff08;1#xff09;标识是否锁住#xff08;2#xff09;加锁#xff08;3#xff09;解锁 2、异步通知#xff08;1#xff09;创建对象#xff08;2示例一、创建和销毁 二、如何实现1、标识1标识是否锁住2加锁3解锁 2、异步通知1创建对象2返回Task3通知完成 3、等待队列1创建队列2 等待加锁3加锁成功 三、完整代码四、使用示例1、基本用法2、尝试加锁3、加锁对比1未加锁2加锁 总结 前言
C#对异步的支持越来越成熟async、await简化了代码也提高了可读性但由于在一段上下文中有了异步操作意味着这段操作可能会被同时重复调用如果本身没有被设计可以重复调用的情况下就很可能会出问题。 一、异步互斥锁的作用是什么
异步互斥锁的作用是用于确保存在异步操作的上下文同步互斥。可以参考flutter的插件mutex功能与本文基本一样。
示例一、创建和销毁
有创建和销毁两个方法两个方法中都有异步操作两个方法可以单独调用但不可以同时调用。 单线程中连续调用创建和销毁不在同一个上下文无法用await如果没有互斥限制有可能出现如下的操作
创建开始-创建异步操作-消息队列-销毁开始-销毁异步操作-消息队列-销毁完成-消息队列-创建完成加入异步互斥锁之后
加锁-创建开始-创建完成-解锁加锁等待-销毁开始-销毁完成-解锁二、如何实现
由于操作都是在单线程我们直接用标识队列就可以实现一个互斥锁。
1、标识
1标识是否锁住
bool _lock false;2加锁
_locktrue;3解锁
_lockfalse;2、异步通知
通过TaskCompletionSource可以实现异步通知
1创建对象
var tcs new TaskCompletionSource();2返回Task
return tcs.Task;3通知完成
tcs.SetResult();3、等待队列
用一个队列来记录等待加锁的请求。
1创建队列
QueueTaskCompletionSource _queue new QueueTaskCompletionSource();2 等待加锁
_queue.Enqueue(tcs);3加锁成功
_queue.Dequeue().SetResult();三、完整代码
/// summary
/// 异步锁非线程锁只能用于单线程异步环境中。
/// /summary
class AsyncMutex
{QueueTaskCompletionSource _queue new QueueTaskCompletionSource();bool _lock false;/// summary/// 获取锁/// /summary/// returns返回Taskawait后即进入了锁/returnspublic Task Acquire(){if (_lock){var tcs new TaskCompletionSource();_queue.Enqueue(tcs);return tcs.Task;}_lock true;return Task.CompletedTask;}/// summary/// 尝试获取锁/// 因为是单线程环境重复调用需要切换上下文否则是无法成功的。/// 比如可以await Task.Delay(30);/// /summary/// returns是否成功/returnspublic bool TryAcquire(){if (_lock) return false;return _lock true;}/// summary/// 释放锁/// /summarypublic void Release(){if (_queue.Count 0){_queue.Dequeue().SetResult();}else{_lock false;}}
}四、使用示例
1、基本用法
直接加锁
AsyncMutex _mtx new AsyncMutex();
async void test()
{await _mtx.Acquire();//custom code_mtx.Release();
}2、尝试加锁
加锁成功才执行操作
AsyncMutex _mtx new AsyncMutex();
void test()
{if (_mtx.TryAcquire()){//custom code_mtx.Release();}
}超时等待
AsyncMutex _mtx new AsyncMutex();
async void test()
{//超时等待300msbool isLock false;for (int i 0; i 10; i){if (isLock _mtx.TryAcquire()) break;await Task.Delay(30);}if (isLock){//custom code_mtx.Release();}
}3、加锁对比
1未加锁
async void test(int num)
{Console.WriteLine(enter num);//模拟异步操作await Task.Delay(10);Console.WriteLine(exit num);
}
//.net 6.0
test(1);
test(2);
test(3);可能出现的组合效果预览
2加锁
AsyncMutex _mtx new AsyncMutex();
async void test(int num)
{await _mtx.Acquire();Console.WriteLine(enter num);//模拟异步操作await Task.Delay(10);Console.WriteLine(exit num);_mtx.Release();
}
//.net 6.0
test(1);
test(2);
test(3);效果预览 总结
以上就是今天要讲的内容本文简单的实现了单线程的异步互斥锁实现起来相对简单但作用还是比较大的。虽然说有些情况的异步是可以在前期设计上避免同时调用比如登录按钮点击后出现蒙板不允许再次点击但是对于已存在的代码出现了同时调用问题此时有互斥锁则可以避免大范围改动代码有效解决问题。