Lockfiles are an anti-pattern if you're developing a library rather than an application, because you can't push your transitive requirements onto the users of your library.
This is why libraries should not use lockfiles, they should be written to safely use as wide a range of dependencies' versions as possible.
It's the developers of an application who should use a lockfile to lock transitive dependencies.
Lockfiles aren't helpful to me here because the entire point is not to be dependent upon specific versions. I actively want to go through the cycle of updating my development environment on a whim, finding that everything breaks, doing the research etc. - because that's how I find out what my version requirements actually are, so that I can properly record them in my own project metadata. And if it turns out that my requirements are narrow, that's a cue to rethink how I use the dependency, so that I can broaden them.
If I had a working environment and didn't want to risk breaking it right at the moment, I could just not upgrade it.
If my requirements were complex enough to motivate explicitly testing against a matrix of dependency versions, using one of those "other tools", I'd do that instead. But neither way do I see any real gain, as a library developer, from a lock file.
The point of a lockfile is to only upgrade when you want to upgrade. I hope you understand that.
Reproducibility is important in many contexts, especially CI, which is why in Node.js world you literally do "npm ci" that installs exact versions for you.
If you haven't found it necessary, it's because you haven't run into situations where not doing this causes trouble, like a lot of trouble.