在C / C ++世界中,使用pthread_once只需执行一次例程即可。在Java中,如果例程已经运行,我通常使用静态原子变量来进行显式检查。但这看起来很难看,因此想知道Java中是否存在类似pthrea_once的东西。
答案 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的并发工具)提供的内容。例如,静态初始化不起作用的变量,没有简单的解决方法(除了考虑初始化是否真的必须是懒惰的)。