Can I, without locking, safely call List.AddRange(r) from multiple threads? If not, what sort of trouble would I run into?
Depending on your usage, SynchronizedCollection could work.
You'd have no single-shot AddRange though. If you are only using this to seed the collection, you can do this as there is an IEnumerable constructor overload.
AddRange
IEnumerable