For example, correct me if I'm wrong, but in Java if you do something like:
MyAwesomeClass myObject = new MyAwesomeClass();
myThreadLocal.set(myObject);
myOtherObject.someField = myObject;
Then the thread local and the field value are references to the same object, in the global heap. Any thread can get to "myOtherObject.someField" and change my thread's local copy.This specific example is probably bad design, but the underlying difference is between a shared memory design and a message passing share-nothing design, where the latter doesn't let you make that kind of mistake.
In Erlang the paradigm is different enough that my bad example doesn't really translate[1], but even if two similar references were made equivalent, they're to _immutable_ objects not references - so from the programmer's point of view they're never shared at all.
In addition, if you want to share something then you send a message so the other process (aka thread) always has their own distinct copy.
[1] The process dictionary is kind of the same as thread local storage, but the kind of state you'd assign via a reference on a mutable field is dealt with differently.