【问题标题】:Making static ReentrantLocks制作静态可重入锁
【发布时间】:2017-12-08 21:12:07
【问题描述】:

我前段时间偶然发现了这个帖子:Does making a reentrant lock static and make it a mutex?,我自己还有一个问题:

如果创建private static final ReentrantLock lock 不被视为代码气味,我感兴趣吗?我读过静态变量是邪恶的,但我目前正在处理的用例看起来像是使用它的理想场所。

有人愿意帮忙吗?

编辑细节:我有这个类,称之为FileProcessor,它在另一个线程中完成给定的工作。我的用例是启动这个类的一些实例并完成这些工作。但我想做的是确保他们中只有一个人会同时完成这项工作,并且他们将轮流执行工作。

所以我想我会给他们一个static ReentrantLock,它将lock() 作为run() 块中的第一件事和unlock() 作为最后一个。这样他们就有了一个共享锁来保护处理同步。

谢谢。

【问题讨论】:

  • 在没有任何上下文的情况下说“静态变量是邪恶的”是没有用的。如果没有看到您的用例,很难说这是否是一个好主意。一般来说,static 没有什么邪恶的。你当然可以滥用它,但你可以滥用很多东西。
  • 编辑并添加了更多细节
  • 使用静态 ReentrantLock 没问题。它似乎很适合您的用例。您也可以使用synchronized (this) {} 来实现相同的目的,而无需使用显式锁定。当然,这并没有提供那么多的粒度。

标签: java multithreading reentrantlock


【解决方案1】:

在类级别使用静态Lock 进行同步是绝对正常的。你也可以使用

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

【讨论】:

  • 赞成,但我认为值得建议发布者考虑使用 ExecutorService。即使您现在不使用非阻塞模型,也可以更轻松地迁移到其中。
【解决方案2】:

有一段时间,使用全局变量是最好的选择。使用并发 API,您可以使用更简单的方法,例如:

  1. 您可以创建一个Runnable 来执行FileProcessor 中的代码并将其提交给Executor。您将执行程序配置为单线程即可。

  2. 如果您有多个可以开始工作的地方,并且您想确保只有一个可以运行。想象一下,您想在程序开始时立即运行它,然后在 16:00 运行它。现在有人在 15:59 开始该程序 - 该作业可能会启动两次。为避免这种情况,请使用 AtomicBoolean 保护代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多