从java内存模型中,我们知道每个线程都有自己的线程堆栈,并且局部变量放在每个线程自己的线程堆栈中。
其他线程无法访问这些局部变量。
那么在这种情况下,我们应该同步局部变量吗?
答案 0 :(得分:16)
您正在谈论以下案例:
public class MyClass {
public void myMethod() {
//Assume Customer is a Class
Customer customer = getMyCustomer();
synchronized(customer) {
//only one thread at a time can access customer object
which ever holds the lock
}
}
}
在上面的代码中, customer
是一个本地引用变量,但您仍在使用同步块来限制对customer
指向的对象的访问(<强>一次通过一个线程)。
在Java内存模型中,对象存在于堆中(即使引用对于存在于堆栈中的Thread是本地的),并且同步只是限制对堆上对象的访问一次线程。
简而言之,当你说局部变量(非原始)时,只有引用是本地的,而不是实际的对象本身,即它实际上指的是堆上的对象,它可以是许多其他线程访问。因此,您需要在对象上进行同步,以便单个线程一次只能访问该对象。
答案 1 :(得分:11)
有两种情况:
int
或double
。ArrayList
。在第一种情况下,无法同步,因为您只能在对象(由引用类型变量指向)上进行同步。
在第二种情况下,这一切都取决于局部变量指向的内容。如果它指向其他线程(也可以)指向的对象,那么您需要确保代码正确同步。
示例:您从static
或实例字段分配了局部变量,或者从共享集合中获取了对象。
但是,如果对象是在您的线程中创建的,并且只分配给该局部变量,并且您从未在线程中向其他线程发出对它的引用,并且对象实现本身也没有给出引用,那么你不必担心同步。
答案 2 :(得分:5)
重点是:同步是出于某种目的。您可以使用它来确保完全一个线程可以在任何给定时间执行一些特殊的保护活动。
因此:如果你需要同步,它总是比一个线程更多。当然,那么你需要锁定那些所有那些线程有权访问的东西。
或换句话说:你锁定门是没有意义的,以防止你自己进入建筑物。
但是,正如另一个答案所指出的那样:它实际上取决于“本地”变量的定义。让我们说你有:
void foo() {
final Object lock = new Object();
Thread a = new Thread() { uses lock
Thread b = new Thread() { uses lock
然后确定,“local”变量可以用作这两个线程的锁。除此之外:该示例有效,因为同步发生在特定对象的监视器上。对象驻留在堆上。所有这些。
答案 3 :(得分:2)
是的,当局部变量用于同步对来自与本地变量相同的方法定义和创建的线程的代码块的访问时,它确实有意义。