Stateless: whenever your call a SLSB then you obtain an instance from the pool and so to different threads will obtain two different instances of the same SLSB. If there is no instance in the pool then either the container will create new instances or the thread has to wait until one becomse availalbe.
Stateful: if every thread creates its own instance of a SFSB there is not problem. If they use the same SFSB I am not quite sure what happens.
Entity: if the Entity Bean is not read-only the container will lock every bean used in the thread and so two threads cannot use the Entity Bean at the same time. Here the same Entity Bean also means the same record in the database. In case of a read-only bean there is nothing to worry.
Message Driven: a user cannot call this bean directly but in general a MDB behaves like a SLSB.
The EJB 2.0 spec makes the behaviour pretty clear. For session beans, section 7.11.8, entity beans 10.5.11, message-driven beans 15.8.3.
Basically session bean instances and message-driven bean instances can't be shared by a thread.
MDB - the container must make it impossible SLSB - the container must make it impossible SFSB - the container throws an exception EB - configurable
The EB case actually has many, many more variations than just read-only or not. The spec doesn't really care read-only, but it is a variation available in current versions of EJB containers. The whole EB situation is as complicated as you want it to be; basically you get the behaviour that you asked the container to provide. Having one instance in one pool for one entity (PK) is common, but not the only option. You could have multiple instances in one pool for one entity (JBoss has this as an option), you could have an instance in a pool acting as multiple entities via activation/passivation callbacks, you can have any of those replicated across multiple pools of different configuration (the read-only vs read-write case fits here), and you can have all of those together in clustered and non-clustered configurations.