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

发布于 2025-01-07 00:21:44 字数 2248 浏览 1 评论 0原文

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

所有这些类都表示它们在 MSDN 库中对于“public static”成员来说是线程安全的。

我的问题是,当用作私有静态而不是 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;
    }

这可能完全取决于我使用的方法本身是否使用共享变量而不是所有方法实例变量...内心的平静会有所帮助,但如果没有必要,我宁愿不必锁定此处的所有内容。

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

谢谢,

迈克,

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

    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);
    }
}

I have the following code with private static members.

All of these classes say that they are thread safe in the MSDN library for "public static" members.

My question is whether these members will be thread safe when used as private static instead of "public static" as stated in the MSDN library.

 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;
    }

This might be entirely dependent on whether the methods I am using themselves use shared variables instead of all method instance variables... some peace of mind would be helpful but I would rather not have to lock everything here if it isn't necessary.

The only reason I locked the random number generator is to limit the possibility of getting the same salt however the chances of this being called by two threads at the same time is very low in my situation.

Thanks,

Mike

This should now be thread safe. I was trying to save on object instantiation overhead but I guess there is a trade off between this and lock waiting. On a high load system lock waiting would likely greatly overpower instantiation overhead and memory usage.

    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);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我爱人 2025-01-14 00:21:44

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

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

此代码可能会因以下原因而失败原因如下:

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

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

更新:

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


1对于 shaM.ComputeHashenc.GetBytes 来说也是如此。

Your code is not thread-safe.

Consider the System.Text.Encoding variable enc. You are calling GetString which is an instance member. The documentation says that only public static members are thread-safe so by inference GetString is not thread-safe because it is not a public static member.1

This code may fail due to the following reasons:

  • You have made no attempt to synchronize access to Encoding.GetString.
  • Encoding.GetString is called from a public static method in your passwordManager class.
  • Public static methods have a high probability of being executed by multiple threads simultaneously.

The reason why public static methods are almost always designed to be thread-safe is because it would be awkward for the caller to always synchronize access to it. You cannot limit multithreaded access to static members like you can with instance members. Consider an ASP.NET application, for example. Web page requests are frequently handled concurrently on separate threads. Do you want to use a lock everytime you call a static method? Of course not. This is a ridiculous burden to place on a developer.

Update:

Your new code is now thread-safe. You will have to do some benchmark tests to see which way is faster: using a lock or instantiating new instances on every call like you have now. I would not be surprised if the lock were faster.


1The same could be said for shaM.ComputeHash and enc.GetBytes.

霊感 2025-01-14 00:21:44

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

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

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

thread safety won't depend on whether something is private or public.

BTW, thread safety document says any public static members of this type, not when this type is embedded as public static.

In short you have to lock your fields like sham, if you are multi-threading.

黯然#的苍凉 2025-01-14 00:21:44

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

You might be better off creating method level variables instead of trying to make synchronise access to shared private fields. That way you will still achieve concurrency as each thread has it's own call stack so will have separate instances of each object and thus allow multiple threads to execute the method simultaneously. If you lock on a shared object then only one thread can execute the method at a time. Another option may be to use the [ThreadStatic] attribute on each field so they will not be shared across threads.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文