Почему локальные переменные потокобезопасны в Java
Я читал многопоточность в Java, и я столкнулся с этим
локальные переменные потокобезопасны в Java.
с тех пор я думал, как/почему локальные переменные потокобезопасны.
кто-нибудь может пожалуйста, дайте мне знать.
8 ответов:
при создании потока он будет иметь свой собственный стек создается. Два потока будут иметь два стека, и один поток никогда не разделяет свой стек с другим потоком.
всем локальным переменным, определенным в вашей программе, будет выделена память в стеке (как прокомментировал Jatin, память здесь означает ссылочное значение для объектов и значение для примитивных типов) (каждый вызов метода потоком создает кадр стека на своем собственном стеке). Как только выполнение метода будет завершено этим потоком, stack frame будут удалены.
есть отличная лекция от стэнфордский профессор в youtube что может помочь вам в понимании этой концепции.
локальные переменные хранятся в стеке каждого потока. Это означает, что локальные переменные никогда не разделяются между потоками. Это также означает, что все локальные примитивные переменные потокобезопасны.
public void someMethod(){ long threadSafeInt = 0; threadSafeInt++; }
локальные ссылки на объекты немного отличаются. Сама ссылка не является общей. Однако указанный объект не хранится в локальном стеке каждого потока. Все объекты хранятся в общей куче. Если объект, созданный локально, никогда не экранирует метод, он был созданный в, это потокобезопасно. Фактически вы также можете передать его другим методам и объектам, пока ни один из этих методов или объектов не сделает переданный объект доступным для других потоков
подумайте о таких методах, как определения функциональности. Когда два потока выполняют один и тот же метод, они никоим образом не связаны. Каждый из них будет создавать свою собственную версию каждой локальной переменной и не сможет взаимодействовать друг с другом каким-либо образом.
Если переменные не являются локальными (например, переменные экземпляра, определенные вне метода на уровне класса), то они присоединяются к экземпляру (а не к одному запуску метода). В этом случае два потока работают одинаково метод оба видят одну переменную, и это не потокобезопасно.
рассмотрим эти два случая:
public class NotThreadsafe { int x = 0; public int incrementX() { x++; return x; } } public class Threadsafe { public int getTwoTimesTwo() { int x = 1; x++; return x*x; } }
в первом, два потока, работающие на одном экземпляре
NotThreadsafe
увидит тот же x. это может быть опасно, потому что потоки пытаются изменить x! Во втором, два потока, работающие на одном экземпляреThreadsafe
увидите совершенно разные переменные, и не могут влиять друг на друга.
В дополнение к другим ответы, такие как Nambari это.
Я хотел бы отметить, что вы можете использовать локальную переменную в методе anoymous type:
этот метод может быть вызван в других потоках, которые могут поставить под угрозу безопасность потоков, поэтому java заставляет все локальные переменные, используемые в анонимных типах, объявляться как окончательные.
рассмотрим этот незаконный код:
public void nonCompilableMethod() { int i=0; for(int t=0; t<100; t++) { new Thread(new Runnable() { public void run() { i++; //compile error, i must be final: //Cannot refer to a non-final variable i inside an //inner class defined in a different method } }).start(); } }
Если бы java разрешил это (например, C# делает через "закрытие"), локальная переменная была бы больше не быть потокобезопасным при любых обстоятельствах. В этом случае значение
i
в конце всех потоков не гарантируется быть100
.
каждый вызов метода имеет свои собственные локальные переменные и, очевидно, вызов метода происходит в одном потоке. Переменная, которая обновляется только одним потоком, по своей сути является потокобезопасной.
, внимательно следите за тем, что именно подразумевается под этим:только записи в саму переменную являются потокобезопасными; вызов методов на объект, на который она ссылается не является по своей сути потокобезопасным. То же самое касается непосредственно обновления переменные объекта.
поток будет иметь свой собственный стек. Два потока будут иметь два стека, и один поток никогда не разделяет свой стек с другим потоком. Локальные переменные хранятся в стеке каждого потока. Это означает, что локальные переменные никогда не разделяются между потоками.
в основном четыре типа хранения существуют в java для хранения информации о классе и данных:
область метода, куча, стек JAVA, ПК
таким образом, область метода и куча разделяются всеми потоками, но каждый поток имеет свой собственный стек JAVA и ПК, и это не разделяется никакими другими потоками.
каждый метод в Java-это как кадр стека. Итак, когда один метод вызывается потоком, который Stack frame загружается в его стек JAVA.Все локальные переменные которые находятся в этом стековом фрейме и связанном стеке операндов, не разделяются другими. ПК будет иметь информацию о следующей инструкции для выполнения в байтовом коде метода. таким образом, все локальные переменные ПОТОКОБЕЗОПАСНЫ.
@Weston также дал хороший ответ.
Мне нравится дженков объяснение
стек потоков содержит все локальные переменные для каждого выполняемого метода (все методы в стеке вызовов). Поток может получить доступ только к своему собственному стеку потоков. Локальные переменные, созданные потоком, невидимы для всех других потоков, кроме потока, который его создал. Даже если два потока выполняют один и тот же код, эти два потока все равно будут создавать локальные переменные этого кода в каждом своем потоке стек. Таким образом, каждый поток имеет свою собственную версию каждой локальной переменной.
все локальные переменные примитивные типы ( логическое, байт, короткие, символ, целое число, длинное, с плавающей точкой, двойной) полностью сохраняются в стеке потоков и, таким образом, не видимым для других потоков. Один поток может передать копию переменной pritimive другому потоку, но он не может совместно использовать примитивную локальную переменную.
кучу содержит все объекты создается в вашем приложении Java, независимо от того, какой поток создал объект. Это включает в себя объектные версии примитивных типов (например, Byte, Integer, Long и т. д.). Не имеет значения, был ли объект создан и назначен локальной переменной или создан как переменная-член другого объекта, объект по-прежнему хранится в куче.
Локальная переменная может иметь значение примитивного типа в этом случае он полностью сохранил в потоке стек.
локальная переменная также может быть ссылка на объект. В этом случае ссылка (локальная переменная) хранится в стеке потоков, а объект сам при хранении в куче.
пожалуйста, прочитайте больше -http://tutorials.jenkov.com/java-concurrency/java-memory-model.html