我需要按字符串锁定一段代码.当然,以下代码非常不安全:
lock("http://someurl")
{
//bla
}
Run Code Online (Sandbox Code Playgroud)
所以我一直在做一个替代品.我通常不会在这里发布大量的代码,但是当涉及到并发编程时,我有点担心我自己的同步方案,所以我提交我的代码来询问是否理智这样做以这种方式或是否有一个更直接的方法.
public class StringLock
{
private readonly Dictionary<string, LockObject> keyLocks = new Dictionary<string, LockObject>();
private readonly object keyLocksLock = new object();
public void LockOperation(string url, Action action)
{
LockObject obj;
lock (keyLocksLock)
{
if (!keyLocks.TryGetValue(url,
out obj))
{
keyLocks[url] = obj = new LockObject();
}
obj.Withdraw();
}
Monitor.Enter(obj);
try
{
action();
}
finally
{
lock (keyLocksLock)
{
if (obj.Return())
{
keyLocks.Remove(url);
}
Monitor.Exit(obj);
}
}
}
private class LockObject
{
private int leaseCount;
public void …Run Code Online (Sandbox Code Playgroud) 当我查看一些遗留应用程序代码时,我注意到它正在使用字符串对象来进行线程同步.我正在尝试解决此程序中的一些线程争用问题,并想知道这是否会导致如此奇怪的情况.有什么想法吗 ?
private static string mutex= "ABC";
internal static void Foo(Rpc rpc)
{
lock (mutex)
{
//do something
}
}
Run Code Online (Sandbox Code Playgroud) 更新:如果这个方法不是线程安全的,这是可以接受的,但我有兴趣学习如何使它保持线程安全.另外,key如果我可以避免它,我不想锁定所有值的单个对象.
原始问题:假设我想编写一个带有键和函数的高阶函数,并检查对象是否已使用给定的密钥进行高速缓存.如果是,则返回缓存的值.否则,运行给定的函数并缓存并返回结果.
这是我的代码的简化版本:
public static T CheckCache<T>(string key, Func<T> fn, DateTime expires)
{
object cache = HttpContext.Current.Cache.Get(key);
//clearly not thread safe, two threads could both evaluate the below condition as true
//what can I lock on since the value of "key" may not be known at compile time?
if (cache == null)
{
T result = fn();
HttpContext.Current.Cache.Insert(key, result, null, expires, Cache.NoSlidingExpiration);
return result;
}
else
return (T)cache;
}
Run Code Online (Sandbox Code Playgroud)
另外,假设我key在编译时不知道所有可能的值.
如何使这个线程安全?我知道我需要在这里引入锁定,以防止1+线程将我的条件评估为真,但我不知道要锁定什么.我读过的许多关于锁定的例子(例如Jon Skeet的文章)建议使用仅用于锁定的"虚拟"私有变量.在这种情况下,这是不可能的,因为密钥在编译时是未知的.我知道我可以通过为每个人使用相同的锁来轻松地使这个线程安全 …
假设我有这个方法:
void Foo(int bar)
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
这是我想要的行为Foo:
如果线程1调用Foo(1)和线程2调用Foo(2),则两个线程可以并发运行.
如果线程1调用Foo(1)和线程2调用Foo(1),则两个线程不能同时运行.
是否有一种良好,标准的方式.net来指定这种行为?我有一个使用对象字典锁定的解决方案,但这感觉有点混乱.
我可以在锁中使用字符串作为锁定器吗?
lock("something")
Run Code Online (Sandbox Code Playgroud)
如果它只有一条线,我可以不用括号锁定吗?
lock("something") foo();
Run Code Online (Sandbox Code Playgroud) 我有一个Web方法上传事务(ASMX Web服务),它接受XML文件,验证文件并将文件内容存储在SQL Server数据库中.我们注意到某些用户可以同时提交两次相同的文件.所以我们可以在我们的数据库中再次使用相同的代码(我们不能在数据库上使用唯一索引或在数据库级别做任何事情,不要问我为什么).我以为我可以在用户id字符串上使用lock语句,但我不知道这是否会解决问题.或者,如果我可以使用兑现对象存储所有用户ID请求并检查我们是否有来自同一用户ID的2个请求,我们将执行第一个请求并阻止第二个请求并显示错误消息,以便任何人有任何想法请帮助
最近我遇到的代码如下:
void CallThisInDifferentThreads(Return return)
{
var lock = "lock";
lock(lock)
{
//Do something here.
}
}
Run Code Online (Sandbox Code Playgroud)
我的第一反应是这段代码中的锁不起作用,因为我们正在创建锁并在同一方法中使用它.调用此方法的每个线程都有自己的锁副本,因此不会有同步.
但后来我意识到这应该有效,因为字符串转到字符串池,并且只有一个特定字符串的实例.我不确定我是否正确.
当需要在动作API中创建文件夹时,是否会涉及任何并发问题?如果是这样,正确的解决方案是使用锁,如下面的代码所示
public async Task<IActionResult> UploadFile(User user){
...
var file = HttpContext.Request.Form.File["SomeFile"];
...
var path = Path.Combile(hostingEnvironment.WebRoot, configurationRoot["BaseDirectory"], user.Id);
lock(path){
if(!Directory.Exists(path)){
Directory.CreateDirectory (path);
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
将path变量用作锁定对象也是合乎逻辑的吗?