[英]C# : Whether this approach is thread-safe
我有一个服务类,它请求一些外部服务。 那个外部服务需要sessionId,这个sessionId的生存时间是未知的(可以是几秒钟,可以是几分钟,可以是几小时,可以是几天。可以是1个请求,可以是1000个请求。没人知道。我们不能完全链接到它。
我创建了一个获取sessionId的方法:
private async Task<string> LoginAsync()
{
using (HttpClient clientLogin = new HttpClient())
{
//....
}
return sessionId;
}
我在我的类中声明了以下变量
public class BillComService : IBillComService
{
private static Lazy<string> SessionId;
并在构造函数中初始化它:
public BillComService()
{
if (SessionId == null)
SessionId = new Lazy<string>(() => LoginAsync().Result);
//....
}
然后我在我的方法中使用它:
private async Task<T> Read<T>(string id, string endpoint)
{
var nvc = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("devKey", devKey),
new KeyValuePair<string, string>("sessionId", SessionId.Value)
};
好的,没关系。 想想sessionId已经过期了。 抛出BillComInvalidSessionException
方法
现在,如果sessionId过期,我会在调用LoginAsync
方法之后编写以下方法来重复我的请求。 常用方法:
private async Task<T> Retry<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (BillComInvalidSessionException)
{
SessionId = new Lazy<string>(() => LoginAsync().Result);
return await Retry(func);
}
}
并Read
:
private async Task<T> ReadWithRetry<T>(string id, string endpoint)
{
return await Retry(async () => await Read<T>(id, endpoint));
}
所以,我的公共方法是:
public async Task<Customer> GetCustomerAsync(string id)
{
return await ReadWithRetry<Customer>(id, "Crud/Read/Customer.json");
}
它的工作原理和工作正常。 但我不确定,它是否是线程安全的:)
不,这不是线程安全的。
当多个线程并行设置共享的SessionId
字段而另一个线程在其他线程正在使用SessionId
时设置SessionId
时,您就有竞争。
顺便说一句:看来你在调用LoginAsync()时错过了等待。
您的代码不执行任何类型的同步,并允许并行发出一个或多个登录。 这是否是一个问题完全取决于发出会话ID的远程实现。
这是我能想到的3个主要场景:
远程登录进程同步每个开发人员密钥的会话ID生成,并保证为并发登录返回相同的会话ID。
远程登录过程将在每次登录时发出新的会话ID,即使在争用情况下也是如此,但所有会话ID都将保持有效。
远程登录过程将为每次登录发出新的会话ID,但每次后续登录都会使给定开发人员密钥的先前发布的会话ID无效。
在方案1和2中,由于并发登录过程,可能发生的最坏情况是效率低下(例如,不必要的网络IO)。
但是,对于方案3,事情可能会变得很难看,因为您可能会在发布后立即失去会话ID,因此您可能会以许多重试循环结束。 会话无效的并发请求越多,会得到的最差。
如果要确保代码是独立于远程实现的安全,那么您必须同步SessionId
读取和写入,这也涉及同步登录过程。 但是,远程实现行为是其服务合同的一部分,因此您的实现也可以合理地考虑该行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.