您能否帮助解释多线程如何访问静态方法?多个线程能够同时访问静态方法吗?静态方法vs实例方法,多线程,性能
对我来说,如果一个方法是静态的,它会使它成为所有线程共享的单个资源,这似乎是合乎逻辑的。因此,一次只能有一个线程使用它。我创建了一个控制台应用程序来测试它。但从我的测试结果看来,我的假设是不正确的。
在我的测试中,构建了多个Worker
对象。每个Worker
都有一些密码和密钥。每个Worker
都有一个实例方法,用它的密钥对密码进行哈希处理。还有一个静态方法,它具有完全相同的实现,唯一的区别是它是静态的。所有Worker
对象已创建后,开始时间将写入控制台。然后引发DoInstanceWork
事件,并且所有Worker
对象都将其useInstanceMethod
排队到线程池。当所有方法或所有对象都完成所有完成所花费的时间时,将从开始时间开始计算并写入控制台。然后将开始时间设置为当前时间,并提高DoStaticWork
事件。这次所有的Worker
对象都将它们的useStaticMethod
排队到线程池。当所有这些方法调用完成所花费的时间,直到他们全部完成后再次计算并写入控制台。
我在等待对象使用实例方法时所用的时间是使用静态方法所花时间的1/8。 1/8,因为我的机器有4个内核和8个虚拟线程。但事实并非如此。事实上,使用静态方法所花费的时间实际上要快得多。
这是怎么回事?引擎盖下发生了什么?每个线程都得到它自己的静态方法的副本吗?
这里是控制台APP-
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Threading;
namespace bottleneckTest
{
public delegate void workDelegate();
class Program
{
static int num = 1024;
public static DateTime start;
static int complete = 0;
public static event workDelegate DoInstanceWork;
public static event workDelegate DoStaticWork;
static bool flag = false;
static void Main(string[] args)
{
List<Worker> workers = new List<Worker>();
for(int i = 0; i < num; i++){
workers.Add(new Worker(i, num));
}
start = DateTime.UtcNow;
Console.WriteLine(start.ToString());
DoInstanceWork();
Console.ReadLine();
}
public static void Timer()
{
complete++;
if (complete == num)
{
TimeSpan duration = DateTime.UtcNow - Program.start;
Console.WriteLine("Duration: {0}", duration.ToString());
complete = 0;
if (!flag)
{
flag = true;
Program.start = DateTime.UtcNow;
DoStaticWork();
}
}
}
}
public class Worker
{
int _id;
int _num;
KeyedHashAlgorithm hashAlgorithm;
int keyLength;
Random random;
List<byte[]> _passwords;
List<byte[]> _keys;
List<byte[]> hashes;
public Worker(int id, int num)
{
this._id = id;
this._num = num;
hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
keyLength = hashAlgorithm.Key.Length;
random = new Random();
_passwords = new List<byte[]>();
_keys = new List<byte[]>();
hashes = new List<byte[]>();
for (int i = 0; i < num; i++)
{
byte[] key = new byte[keyLength];
new RNGCryptoServiceProvider().GetBytes(key);
_keys.Add(key);
int passwordLength = random.Next(8, 20);
byte[] password = new byte[passwordLength * 2];
random.NextBytes(password);
_passwords.Add(password);
}
Program.DoInstanceWork += new workDelegate(doInstanceWork);
Program.DoStaticWork += new workDelegate(doStaticWork);
}
public void doInstanceWork()
{
ThreadPool.QueueUserWorkItem(useInstanceMethod, new WorkerArgs() { num = _num, keys = _keys, passwords = _passwords });
}
public void doStaticWork()
{
ThreadPool.QueueUserWorkItem(useStaticMethod, new WorkerArgs() { num = _num, keys = _keys, passwords = _passwords });
}
public void useInstanceMethod(object args)
{
WorkerArgs workerArgs = (WorkerArgs)args;
for (int i = 0; i < workerArgs.num; i++)
{
KeyedHashAlgorithm hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
hashAlgorithm.Key = workerArgs.keys[i];
byte[] hash = hashAlgorithm.ComputeHash(workerArgs.passwords[i]);
}
Program.Timer();
}
public static void useStaticMethod(object args)
{
WorkerArgs workerArgs = (WorkerArgs)args;
for (int i = 0; i < workerArgs.num; i++)
{
KeyedHashAlgorithm hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
hashAlgorithm.Key = workerArgs.keys[i];
byte[] hash = hashAlgorithm.ComputeHash(workerArgs.passwords[i]);
}
Program.Timer();
}
public class WorkerArgs
{
public int num;
public List<byte[]> passwords;
public List<byte[]> keys;
}
}
}
+1代码与数据。 – 2012-03-11 14:17:25
感谢您对方法是只读资源的说明。我认为我理解的巨大差距在于同一资源如何被多个线程同时读取。我认为这对于对计算机的基本理解是相当重要的。我想我在下意识地想着一个方法只能在每个时钟周期读取一次,当我猜测它实际上可以为许多线程读取很多次。但是,说这些读取只是出现并发是真的,因为它们都发生在一个时钟周期内?另外如何读取一个方法?一次或分段?谢谢 – 2012-03-11 14:56:02