您能否幫助解釋多線程如何訪問靜態方法?多個線程能夠同時訪問靜態方法嗎?靜態方法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