Java中是否有pthread_once等价物?

时间:2014-08-19 05:29:14

标签: java concurrency

在C / C ++世界中,使用pthread_once只需执行一次例程即可。在Java中,如果例程已经运行,我通常使用静态原子变量来进行显式检查。但这看起来很难看,因此想知道Java中是否存在类似pthrea_once的东西。

1 个答案:

答案 0 :(得分:1)

由于您引用“静态原子变量”,您似乎在讨论static资源,如果您在类初始化程序本身中初始化它们,则不需要特殊操作:

class Foo {
  static ResourceType X = createResource();
}

此处,createResource()将在第一次使用Foo时以线程安全的方式执行一次,例如第一次访问Foo.X时。在类初始化过程中访问X的线程被强制等待,但后续访问将在没有任何同步开销的情况下执行。通常,但不一定,变量也将被声明为final

如果您有多个资源的创建应该独立延迟,那么所有者类可能会使用内部类,每个类都拥有一个资源。

如果你的问题是关于一个应该只执行一次但没有返回值的动作,那么也可以使用静态初始化。您只需添加一个可以访问的成员来触发类初始化,例如:

class Foo {
  static { performAction(); }
  static void performActionOnce() {}
}

此处,调用Foo.performActionOnce()将导致performAction()第一次执行,而所有其他后续调用都不执行任何操作。即使第一次调用存在争用,您也可以依赖于从performActionOnce()返回performAction()内的操作,即使第一次调用存在争用。


这与任何原子变量方法不同,因为原子变量不能为第一次调用争用的情况提供足够的等待能力。如果将原子变量与等待队列组合在一起,最终会得到Lock(或任何其他基于AQS的并发工具)提供的内容。例如,静态初始化不起作用的变量,没有简单的解决方法(除了考虑初始化是否真的必须是懒惰的)。