Czytałem przez post tips and tricks i myślałem, że wypróbuję niektóre rzeczy z C#, których nigdy wcześniej nie robiłem. Dlatego poniższy kod nie służy faktycznemu celowi, ale jest tylko "funkcją testową", aby zobaczyć, co się stanie.C# ThreadStatic + członkowie volatile nie działają zgodnie z oczekiwaniami
W każdym razie, mam dwie statyczne prywatne pola:
private static volatile string staticVolatileTestString = "";
[ThreadStatic]
private static int threadInt = 0;
Jak widać, jestem testowania ThreadStaticAttribute i lotnej hasła.
W każdym razie, mam metody badawczej, która wygląda tak:
private static string TestThreadStatic() {
// Firstly I'm creating 10 threads (DEFAULT_TEST_SIZE is 10) and starting them all with an anonymous method
List<Thread> startedThreads = new List<Thread>();
for (int i = 0; i < DEFAULT_TEST_SIZE; ++i) {
Thread t = new Thread(delegate(object o) {
// The anon method sets a newValue for threadInt and prints the new value to the volatile test string, then waits between 1 and 10 seconds, then prints the value for threadInt to the volatile test string again to confirm that no other thread has changed it
int newVal = randomNumberGenerator.Next(10, 100);
staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " setting threadInt to " + newVal;
threadInt = newVal;
Thread.Sleep(randomNumberGenerator.Next(1000, 10000));
staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " finished: " + threadInt;
});
t.Start(i);
startedThreads.Add(t);
}
foreach (Thread th in startedThreads) th.Join();
return staticVolatileTestString;
}
Co bym spodziewać wrócił z tej funkcji jest wyjście tak:
thread 0 setting threadInt to 88
thread 1 setting threadInt to 97
thread 2 setting threadInt to 11
thread 3 setting threadInt to 84
thread 4 setting threadInt to 67
thread 5 setting threadInt to 46
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88
Jednak to, co Rozumiem:
thread 0 setting threadInt to 88
thread 4 setting threadInt to 67
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88
Druga "połowa" wyniku jest zgodna z oczekiwaniami (co, jak sądzę, oznacza w polu ThreadStatic działa tak, jak myślałem), ale wydaje się, że kilka początkowych wyników zostało "pominiętych" od pierwszej "połowy".
Dodatkowo wątki w pierwszej "połowie" są nieczynne, ale rozumiem, że wątek nie uruchamia się natychmiast po wywołaniu Start(); ale zamiast tego wewnętrzne elementy sterujące OS będą uruchamiać wątki według własnego uznania.
EDIT: Nie oni nie, rzeczywiście, po prostu uważamy, że były, bo mój mózg nie zdobywa kolejne numery
Więc moje pytanie brzmi: Co się dzieje źle powodować mnie stracić kilka linii w pierwsza "połowa" produkcji? Na przykład, gdzie jest linia "wątku 3 ustawienie wątkuInt do 84"?
Uruchomiłem twój kod kilka razy i zawsze otrzymuję oczekiwany wynik ... –
Założę się, że gdzieś w dole, połączenie z + = na łańcuchu uzyskuje wartość przed ustawieniem poprzedniego wątku i nowy wątek nadpisuje go nową wartością (dlatego wątek 1 miał pominięty wynik). – Charleh
@DannyChen Mam czterordzeniowy rdzeń i nie jest to jedyny kod w tej aplikacji; nie wiem, czy któryś z nich miałby sens. Mogę przesłać cały kod gdzieś (to tylko dwa pliki .cs), jeśli chcesz? – Xenoprimate