Функции - это код, который затем выполняется в контексте памяти. Код может выполняться много раз параллельно ( буквально параллельно на многопроцессорной машине), но каждый из этих вызовов будет выполняться в различном контексте памяти (с точки зрения локальных переменных и т. Д.). ). На низком уровне это работает, потому что функции будут ссылаться на локальные переменные как смещения в памяти для чего-то, называемого « stack », на которое указывает регистр процессора, называемый «указатель стека» (или в некоторых интерпретируемых языках). аналог этого регистра на более высоком уровне), и значение этого регистра будет различным для разных вызовов функции. Таким образом, локальная переменная x
в одном вызове функции foo
находится в другом месте в памяти, чем локальная переменная x
в другом вызове foo
, независимо от того, происходят ли эти вызовы одновременно.
Переменные экземпляра разные, на них ссылаются через ссылку (указатель) на память, выделенную для экземпляра объекта. Две работающие копии одной и той же функции могут обращаться к одной и той же переменной экземпляра в точно в одно и то же время; аналогично, две разные функции могут сделать это. Вот почему мы сталкиваемся с проблемами "потоков" или параллелизма , синхронизацией, блокировками , условиями гонки и т. Д. Но это также одна из причин того, что вещи могут быть очень эффективными .