假设我有一个静态助手类,我在Web应用程序中使用了很多。假设应用程序在一段持续的时间内每秒接收大约20个请求,并且通过魔术,两个请求要求静态类在完全相同的纳秒内完成一些工作。
发生这种情况会发生什么?
为了提供一些上下文,该类用于执行linq-to-sql查询:它接收一些参数,包括UserID,并返回自定义对象列表。
感谢。
答案 0 :(得分:6)
这完全取决于你的“一些工作”意味着什么。如果它不涉及任何共享状态,那就绝对没问题。如果它需要访问共享状态,您将需要解决如何以线程安全的方式处理它。
一般的经验法则是类的公共API对于静态方法应该是线程安全的,但对于实例方法不必是线程安全的 - 通常任何一个实例都只是在单个线程中使用。当然这取决于你班级的工作,what you mean by thread-safe。
答案 1 :(得分:4)
发生这种情况会发生什么?
如果您的方法是reentrant,那么它们是线程安全的,将会发生的是它们可能会起作用。如果这些静态方法依赖于某些共享状态而您尚未同步访问此状态,则此共享状态可能会被破坏。但是你不需要在相同纳秒的时间内通过20个请求来破坏你的共享状态。如果你不同步它,那么2就足够了。
所以静态方法本身并不是邪恶的(实际上它们不是单元测试友好的,但这是另一个主题),它是在多线程环境中实现它们的方式。所以你应该让它们安全线程。
更新:
因为在注释部分中提到了LINQ-TO-SQL,只要静态方法中使用的所有变量都是本地的,所以此方法是线程安全的。例如:
public static SomeEntity GetEntity(int id)
{
using (var db = new SomeDbContext())
{
return db.SomeEntities.FirstOrDefault(x => x.Id == id);
}
}
答案 2 :(得分:2)
您必须确保您的方法是线程安全的,因此不要使用静态属性来存储任何类型的状态。如果要在静态方法中声明新对象,则没有问题,因为每个线程都有自己的对象。
答案 3 :(得分:1)
这取决于静态类是否具有任何状态(即所有调用共享的静态变量)。如果没有,那就没关系。如果确实如此,那就不好了。例子:
// Fine
static class Whatever
{
public string DoSomething() {
return "something";
}
}
// Death from above
static class WhateverUnsafe
{
static int count = 0;
public int Count() {
return ++count;
}
}
您可以使用锁定使第二项工作正常,但随后会引入死锁和并发问题。
我使用静态类构建了大量的Web应用程序,但它们从来没有任何共享状态。
答案 4 :(得分:0)
它以一种讨厌的方式崩溃(如果你这样做是为了共享状态),避免在webapp中这样做......或者用锁来保护读/写:
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
但说实话,你真的应该避免使用静态,除非你真的必须这样做,如果你真的需要你必须非常小心你的锁定策略并测试它以破坏它以确保已经设法隔离读取和写入彼此