One list is traversed when committing blocks, so a linked list was never necessary - just a commit-list (vector of pointers).
Another list is traversed when dequeueing the next lock, so again: a linked list isn't necessary, just a dequeue (which might not have to be serialised).
Another list is traversed when finding the next blocked reader, but again serialisation wasn't required here.
And so on.
However when you have the right data structure, you'll find you won't need it.
Benchmarking is important because searching for the right data structure is time consuming (expensive for the programmer) and it's usually not necessary.
I built something once that used intrusive skiplists because it needed to expire elements using one ordering and search them by another. It would have been much less efficient if I'd have broken it up into multiple flat representations.
(Actually, it was flat, but explaining that aspect of it is quite difficult).