这些私有静态成员是线程安全的吗

本文关键字:线程 安全 静态成员 | 更新日期: 2023-09-27 18:25:19

我有以下带有私有静态成员的代码。

所有这些类都表示,对于"publicstatic"成员,它们在MSDN库中是线程安全的。

我的问题是,当这些成员用作私有静态而不是MSDN库中所说的"公共静态"时,它们是否是线程安全的。

 public static class passwordManager
{
    private static System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
    private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
    private static System.Text.Encoding enc = System.Text.Encoding.ASCII;
    public static string produceSalt(int size)
    {
        byte[] by = new byte[size];
        lock (rand)
        {
            rand.GetBytes(by);
        }
        return enc.GetString(by, 0, by.Length);
    }
    public static string encryptPassword(string password, string salt){
        return enc.GetString(shaM.ComputeHash(enc.GetBytes(password + salt)));
    }
    public static bool isCorrectPassword(string inputPassword, string DBsalt, string DBpassword)
    {
        return encryptPassword(inputPassword, DBsalt) == DBpassword;
    }

这可能完全取决于我使用的方法本身是否使用共享变量,而不是所有方法实例变量。。。如果没有必要,我宁愿不把所有东西都锁在这里。

我锁定随机数生成器的唯一原因是限制获得相同salt的可能性,但在我的情况下,两个线程同时调用的可能性非常低。

谢谢,

Mike

这现在应该是线程安全的。我试图节省对象实例化开销,但我想这和锁等待之间有一个折衷。在高负载系统上,锁等待可能会大大超过实例化开销和内存使用。

    public static class passwordManager
{
    private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
    public static byte[] produceSalt(int size)
    {
        byte[] by = new byte[size];
        lock (rand)
        {
            rand.GetBytes(by);
        }
        return by;
    }
    public static byte[] encryptPassword(string password, byte[] salt){
        System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
        System.Text.Encoding enc = new System.Text.UTF8Encoding();
        return shaM.ComputeHash(concatArrays(enc.GetBytes(password), salt));
    }
    public static bool isCorrectPassword(string inputPassword, byte[] DBsalt, byte[] DBpassword)
    {
        return compare(encryptPassword(inputPassword, DBsalt), DBpassword);
    }
}

这些私有静态成员是线程安全的吗

您的代码不是线程安全的。

考虑System.Text.Encoding变量enc。您正在调用作为实例成员的GetString。文档指出,只有公共静态成员是线程安全的,因此推断GetString不是线程安全的因为它不是公共静态成员1

此代码可能由于以下原因而失败:

  • 您没有尝试同步对Encoding.GetString的访问
  • Encoding.GetString是从passwordManager类中的公共静态方法调用的
  • 公共静态方法同时被多个线程执行的概率很高

公共静态方法几乎总是被设计为线程安全的原因是,调用方总是同步对它的访问会很尴尬。你不能像对实例成员那样限制对静态成员的多线程访问。考虑一个ASP。NET应用程序。网页请求经常在单独的线程上同时处理。是否每次调用静态方法时都要使用lock?当然不是。这对开发人员来说是一个荒谬的负担。

更新:

您的新代码现在是线程安全的。您必须进行一些基准测试,看看哪种方法更快:使用lock或像现在这样在每次调用中实例化新实例。如果lock更快,我不会感到惊讶。


对于CCD_ 11和CCD_。

线程安全性不取决于某个东西是私有的还是公共的。

顺便说一句,线程安全文档说这个类型的任何公共静态成员,而不是当这个类型被嵌入为公共静态时。

简而言之,如果你是多线程的,你必须像sham一样锁定你的字段。

您最好创建方法级变量,而不是尝试同步访问共享的私有字段。这样,您仍然可以实现并发性,因为每个线程都有自己的调用堆栈,因此每个对象都有单独的实例,从而允许多个线程同时执行该方法。如果锁定共享对象,那么一次只能有一个线程执行该方法。另一种选择可能是在每个字段上使用[ThreadStatic]属性,这样它们就不会在线程之间共享。