We need to take the state lock here to ensure that we're not currently just before setting the state of this child element. Otherwise it can happen that we removed the element here and e.g. set it to NULL state, and shortly afterwards have another thread set it to a higher state again as part of a state change for the whole bin.
When adding an element to the bin this is not needed as we require callers to always ensure after adding to the bin that the new element is set to the correct state.
This is reliably reproducible in one application I have here after 14 to 20 hours.
gst_element_set_locked_state() is racy if not called with the state lock of the parent bin: the parent bin might've just checked the flag and would next proceed to change the child's state.