I have a dictionary which is filled once in a static constructor and stays unchanged ever since. I want multiple threads to be able to read values from this collection. Do I need any locking here?
No. Locking is only required when you have the possibility of interleaving multiple writes or writes with reads. Reading only, with no changes at all doesn't introduce the possibility of what one thread is doing affecting what another thread is doing.
Note that this requires no writes, at all. If, say, you're using an object and reading it somehow modifies the internal state of the object as a side effect, then you'd need to have locking still.
Edit: It appears the docs say this class is thread safe for reading. But it if didn't the answer below still applies since you can't assume your read only is read only for the class.
The short answer is yes. Unless the class says it is thread safe. There are a lot of things it could be doing that are not thread safe.
It's likely it won't cause a problem but the class could be using internal variables in a way that could cause race conditions. It could also be calling other classes that are not thread safe. Unless you check the code of the docs says it's OK then it is not safe to assume.
For example you may think it is read only but the class trying to speed things up may cache the last item accessed which involves writting data. That could fail causing you to retrieve a different item than expected.
Again I don't think that is likely here but unless the class says it is thread safe it is dangerous to assume.
According to Microsoft's documentation, the Dictionary class can support multiple readers concurrently, as long as the collection is not modified. Therefore, no locks are required.