Я читал многопоточность в Java, и я сталкивался с этим
Локальные переменные являются потокобезопасными в Java.
С тех пор я думал, как/Почему локальные переменные являются потокобезопасными.
Может кто-нибудь, пожалуйста, дайте мне знать.
Я читал многопоточность в Java, и я сталкивался с этим
Локальные переменные являются потокобезопасными в Java.
С тех пор я думал, как/Почему локальные переменные являются потокобезопасными.
Может кто-нибудь, пожалуйста, дайте мне знать.
Когда вы создаете поток, у него будет свой собственный стек. Два потока будут иметь два стека, а один поток никогда не будет делиться своим стеком с другим потоком.
Все локальные переменные, определенные в вашей программе, будут выделены в стеке в стеке (как прокомментировал Jatin, здесь здесь означает ссылочное значение для объектов и значение для примитивных типов) (Каждый вызов метода потоком создает фрейм стека самостоятельно стек). Как только выполнение метода будет завершено этим потоком, стек стека будет удален.
Есть замечательная лекция Стэнфордский профессор в 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's.
Я хотел бы указать, что вы можете использовать локальную переменную в методе 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 разрешило это (например, С# делает через "закрытие" ), локальная переменная перестала быть потокобезопасной при любых обстоятельствах. В этом случае значение i
в конце всех потоков не гарантируется 100
.
Каждый вызов метода имеет свои собственные локальные переменные и, очевидно, вызов метода происходит в одном потоке. Переменная, которая обновляется только одним потоком, по своей сути является потокобезопасной.
Однако, внимательно следите за тем, что именно подразумевается под этим: только записи в эту переменную являются потокобезопасными; вызывающие методы на объекте, которые он ссылается на , по сути не являются потокобезопасными. То же самое касается непосредственного обновления переменных объекта.
В потоке будет свой собственный стек. Два потока будут иметь два стека, а один поток никогда не делится своим стеком с другим потоком. Локальные переменные хранятся в каждом потоке собственного стека. Это означает, что локальные переменные никогда не разделяются между потоками.
В основном четыре типа хранилища находятся в java для хранения информации о классе и данных:
Область метода, куча, стек JAVA, ПК
поэтому область "Метод" и "Куча" разделяются всеми потоками, но каждый поток имеет свой собственный стек JAVA и ПК и который не используется другими нитями.
Каждый метод в java является фреймом Stack. поэтому, когда один метод вызывается потоком, который стек стека загружается в его стек JAVA. Вся локальная переменная, которая присутствует в этом стеке стека и связанный стек операнда, не разделяется другими. ПК будет иметь информацию о следующей инструкции для выполнения в байтовом методе метода. поэтому все локальные переменные являются БЕЗОПАСНЫМИ РЕЖИМАМИ.
@Weston также дал хороший ответ.
Мне нравится Дженков объяснение
Стек потока содержит все локальные переменные для каждого выполняемого метода (все методы в стеке вызовов). Поток может получить доступ только к своему стеку потоков. Локальные переменные, созданные потоком, невидимы для всех других потоков, кроме потока, который его создал. Даже если два потока исполняют один и тот же код, эти два потока все равно будут создавать локальные переменные этого кода в каждом своем стеке потоков. Таким образом, каждый поток имеет свою версию каждой локальной переменной.
Все локальные переменные примитивных типов (логические, байтовые, короткие, char, int, long, float, double) полностью хранятся в стеке потоков и поэтому не видны другим потокам, Один поток может передать копию примитивной переменной другому потоку, но он не может совместно использовать примитивную локальную переменную.
Куча содержит все объекты, созданные в приложении Java, независимо от того, какой поток создал объект. Это включает в себя версии объектов примитивных типов (например, Byte, Integer, Long и т.д.). Неважно, был ли объект создан и назначен локальной переменной или создан как переменная-член другого объекта, этот объект все еще сохраняется в куче.
Локальная переменная может быть примитивного типа, и в этом случае она полностью сохраняется в стеке потоков.
Локальная переменная также может быть ссылкой на объект. В этом случае ссылка (локальная переменная) сохраняется в стеке потоков, но сам объект object, если он хранится в куче.
Пожалуйста, прочитайте больше здесь