I think that race conditions among the threads might be avoided more safely using a semaphore file, which is separate from the actual data that you're manipulating. I posted a handy module drawn from an excellent article in TPJ by Sean Burke on this subject -- the code
is here, and the commentary includes a reference to the article.
(update: then again, since I haven't yet looked closely at the docs for Hash::Util, maybe that module covers the matter well enough. If so, it might be more efficient -- or might be worth benchmarking, if your deletion code ends up consuming a lot of run-time.)