Making static ReentrantLocks

2019-07-15 03:35发布

问题:

I've stumbled upon this thread some time ago: Does making a reentrant lock static and make it a mutex? and I have an additional question on my own:

Im interested if creating a private static final ReentrantLock lock is not considered a code smell? I've read that static variables are evil, yet my current use case Im working on looks like ideal place to use one.

Anyone care to help?

Edit with details: I have this class, call it FileProcessor which does a given job in another thread. My use case is spinning up a few of these instances of this class and doing those jobs. But what I want to do is to make sure only one of them will make this job at once and they will take turns in performing the work.

So I figured out Ill give them a static ReentrantLock that will lock() as first thing in run() block and unlock() as last. This way they have a shared lock that will guard the processing synchronization.

Thanks.

回答1:

Using a static Lock for synchronization at the class level is absolutely normal. You can also use

synchronized (FileProcessor.class) {
    //your code
}


回答2:

For some time, using a global variable was the best option. With the Concurrency API, you have much more simple approaches, for example:

  1. You can create a Runnable that executes the code in FileProcessor and submit it to an Executor. You configure the executor to single threaded and you're done.

  2. If you have several places where you can start a job and you want to make sure that only one ever runs. Imagine you want to run it right when the program starts and then at 16:00. Now someone starts the program at 15:59 - the job might be started twice. To avoid this, protect the code with an AtomicBoolean:

    private AtomicBoolean guard = new AtomicBoolean(true);
    
    if (guard.getAndSet(false)) {
        try {
            ... do job ...
        } finally {
            guard.set(true);
        }            
    }