Ich sehe viele Antworten, aber keine, die wirklich auf den Grund hinweisen.
Das kann so gedacht werden,
Immer wenn ein Thread erstellt wird, wird er mit seinem eigenen Stack erstellt (ich schätze, die Größe des Stacks zum Zeitpunkt der Erstellung beträgt ungefähr 2 MB). Also findet jede Ausführung tatsächlich im Kontext dieses Thread-Stacks statt.
Jede erstellte Variable lebt im Heap, aber ihr Verweis lebt im Stack, mit Ausnahmen von statischen Variablen, die nicht im Thread-Stack leben.
Jeder Funktionsaufruf, den Sie machen, wird tatsächlich auf den Thread-Stack geschoben, sei es statisch oder nicht statisch. Da die komplette Methode auf den Stack geschoben wurde, lebt jede Variableerstellung im Stack (wieder mit Ausnahmen von statischen Variablen) und ist nur für einen Thread zugänglich.
Also sind alle Methoden thread-sicher, bis sie den Zustand einer statischen Variable ändern.