考虑一个场景:
MySessionObject object = Session.getObject();
//then object is passed to Runnable task.
private class MyTask implements Runnable {
private final MySessionObject object;
public SaveVisitorTask(MySessionObject object) {
this.object = object;
}
@Override
public void run() {
MyDao dao = new MyDao();
MySessionObject savedObject = dao.save(object);
this.object.setId(savedObject.getId());
}
}
说明
问题很简单 - 代码线程安全吗?很明显,线程局部变量(session)不能
被共享到线程,但它拥有的引用怎么样?声明this.object.setId(savedObject.getId());
是否会影响原始对象?
P.S。如果此代码不是线程安全的(我个人认为)可以解释为什么?
答案 0 :(得分:0)
查看Java Atomic Variables。
原子操作将完成或根本不完成。其他线程将无法看到“正在进行”的操作。它永远不会被视为部分完整的状态。
答案 1 :(得分:0)
语句this.object.setId(savedObject.getId());
实际上影响了原始对象。因为在其他线程中没有从本地线程检索object
,而是直接将其传递给其他线程。
如果你在第二个帖子中调用Session.getObject();
,那么它将返回一个特定于线程的对象副本。
答案 2 :(得分:0)
很明显,线程局部变量(session)无法共享 线程,但它拥有的引用呢?
ThreadLocal
变量放在场景后面的Thread
类中的特殊地图中,此地图维护设置的值。 map中条目的键是调用线程本身,value是由" set"设置的值。 ThreadLocal
的方法。
public class Thread implements Runnable {
..................
..................
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
现在他们在这里结束的原因是因为在某些时候,一段代码(在一个方法内)运行了一个名为" set"在Threadlocal上创建一个条目到threadlocals映射,其中key作为线程,值作为对象集。
public class ThreadLocal<T> {
.........
.........
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
}
因此,只要设置的变量没有从线程方法堆栈中逃脱,它对每个线程都是唯一的,因此是线程安全的。但是,如果它指向某个共享变量(如类的实例变量),则有可能多个线程指向threadlocal映射中的同一个对象。在这种情况下 - 它绝对不是线程安全的。 Threadlocal的文档也提到了这一点:
每个线程都拥有对其本地线程副本的隐式引用 只要线程是活动的并且是ThreadLocal实例的变量 可以访问;一个线程消失后,它的所有线程局部实例副本都会被垃圾收集(除非其他 存在对这些副本的引用。)