在两个相同的条件语句之间锁定是好的模式吗?
Is locking between two same conditional statements good pattern?
我正在写一个网络应用程序,所以关注并发性。我需要使用每 10 分钟过期的令牌调用 API,因此在每次 API 调用之前,我需要检查新令牌。
我没有任何并发设计的经验,所以这就是我正在做的,我需要有人来澄清我是否做得好。它是反模式吗?注意:class本身是单例的。
private object tokenLock = new object();
private void RequestApi ()
{
if (DateTime.UtcNow >= this.TokenExpireTime)
{
lock (this.tokenLock)
{
if (DateTime.UtcNow >= this.TokenExpireTime)
{
// Request new Token
// Update new Token Expiration Time
}
}
}
// Request API
}
为了防止重复代码,我可以改写成属性(逻辑还是一样):
private void RequestApi ()
{
if (this.NeedNewToken)
{
lock (this.tokenLock)
{
if (this.NeedNewToken)
{
// Request new Token
// Update new Token Expiration Time
}
}
}
// Request API
}
private bool NeedNewToken => DateTime.UtcNow >= this.TokenExpireTime;
你应该摆脱外部的、不同步的比较。
首先,您使用的模式称为 "double-checked locking"。它通常仅在争用程度高且需要锁定的可能性低的情况下使用,证明代码的笨拙。
仅凭这一点,您不太可能真的需要在这种情况下使用它。不过,我承认在这方面,这个问题是见仁见智的。
但更重要的是,双重检查锁定取决于您能够在没有同步的情况下安全地自行进行条件测试,而这里不是这种情况。 DateTime
值不是原始值,因此在没有同步的情况下无法安全访问。否则,您 运行 有获得 "torn" 值的风险,即部分写入的值,因此既不是旧值也不是新值。
在这方面,这个问题不是见仁见智的问题。该代码根本不正确,需要修复。只需拿起锁,然后在锁内做任何你需要做的事情。不要试图通过不同步的比较走捷径。在这种情况下不安全。
我正在写一个网络应用程序,所以关注并发性。我需要使用每 10 分钟过期的令牌调用 API,因此在每次 API 调用之前,我需要检查新令牌。
我没有任何并发设计的经验,所以这就是我正在做的,我需要有人来澄清我是否做得好。它是反模式吗?注意:class本身是单例的。
private object tokenLock = new object();
private void RequestApi ()
{
if (DateTime.UtcNow >= this.TokenExpireTime)
{
lock (this.tokenLock)
{
if (DateTime.UtcNow >= this.TokenExpireTime)
{
// Request new Token
// Update new Token Expiration Time
}
}
}
// Request API
}
为了防止重复代码,我可以改写成属性(逻辑还是一样):
private void RequestApi ()
{
if (this.NeedNewToken)
{
lock (this.tokenLock)
{
if (this.NeedNewToken)
{
// Request new Token
// Update new Token Expiration Time
}
}
}
// Request API
}
private bool NeedNewToken => DateTime.UtcNow >= this.TokenExpireTime;
你应该摆脱外部的、不同步的比较。
首先,您使用的模式称为 "double-checked locking"。它通常仅在争用程度高且需要锁定的可能性低的情况下使用,证明代码的笨拙。
仅凭这一点,您不太可能真的需要在这种情况下使用它。不过,我承认在这方面,这个问题是见仁见智的。
但更重要的是,双重检查锁定取决于您能够在没有同步的情况下安全地自行进行条件测试,而这里不是这种情况。 DateTime
值不是原始值,因此在没有同步的情况下无法安全访问。否则,您 运行 有获得 "torn" 值的风险,即部分写入的值,因此既不是旧值也不是新值。
在这方面,这个问题不是见仁见智的问题。该代码根本不正确,需要修复。只需拿起锁,然后在锁内做任何你需要做的事情。不要试图通过不同步的比较走捷径。在这种情况下不安全。