使用同步(锁定对象)块时,静态锁定对象是否需要是最终的?
Does a static lock object need to be final when using a synchronized(lock object) block?
假设我有一个
private static Object lock = new Object();
和同一个地方class
public void run() {
synchronized(lock) {
//only 1 thread here, all others wait
}
}
我总是读到锁对象应该是最终的,但不完全是为什么。
假设我 100% 知道我的代码不会在任何地方触及锁定对象,
如果省略了 final 关键字,这是否意味着同步不是 100% 防弹?
如果没有您所依赖的 final 修饰符,但是对象已被初始化以使其正确可见,并假设没有任何改变其值。由于它是静态的,因此在加载 class 时会发生初始化并且存在可见性保证,因此从技术上讲,您可以将其保留为非最终状态。 (虽然代码使用同步块,但当然在进入块之前必须评估正在使用的锁。)
如果锁定对象在使用时被更改为另一个,那么两个线程可能处于同一段受保护代码中,整个锁定方案就会受到损害。在此处添加 final 关键字意味着编译器正在帮助您确保此锁不会更改,如果有人稍后尝试更改它,将导致编译错误。
从编译器那里获得尽可能多的帮助通常是一件好事,并且编译会告诉你该字段是否已更改,因此这是一个低风险的更改,可以确保一个大的问题不可能发生。
在此上下文中使用 final
只是一种很好的做法。
您可以使用任何对象进行同步,final
或非最终对象,static
或非静态对象。
一起使用 final
和 static
将为您提供安全性,因为没有人会在不同的锁上同步相同的代码。如果不使用 final
,您不确定代码中某处是否未重新分配该变量。
一般来说,对一个在初始化后永远不会重新分配的变量使用 final
是一个很好的编程习惯。它提高了可读性,因为阅读你的代码的人都知道,如果不阅读完整的代码,这个变量也永远不会被重新分配。
假设我有一个
private static Object lock = new Object();
和同一个地方class
public void run() {
synchronized(lock) {
//only 1 thread here, all others wait
}
}
我总是读到锁对象应该是最终的,但不完全是为什么。 假设我 100% 知道我的代码不会在任何地方触及锁定对象, 如果省略了 final 关键字,这是否意味着同步不是 100% 防弹?
如果没有您所依赖的 final 修饰符,但是对象已被初始化以使其正确可见,并假设没有任何改变其值。由于它是静态的,因此在加载 class 时会发生初始化并且存在可见性保证,因此从技术上讲,您可以将其保留为非最终状态。 (虽然代码使用同步块,但当然在进入块之前必须评估正在使用的锁。)
如果锁定对象在使用时被更改为另一个,那么两个线程可能处于同一段受保护代码中,整个锁定方案就会受到损害。在此处添加 final 关键字意味着编译器正在帮助您确保此锁不会更改,如果有人稍后尝试更改它,将导致编译错误。
从编译器那里获得尽可能多的帮助通常是一件好事,并且编译会告诉你该字段是否已更改,因此这是一个低风险的更改,可以确保一个大的问题不可能发生。
在此上下文中使用 final
只是一种很好的做法。
您可以使用任何对象进行同步,final
或非最终对象,static
或非静态对象。
一起使用 final
和 static
将为您提供安全性,因为没有人会在不同的锁上同步相同的代码。如果不使用 final
,您不确定代码中某处是否未重新分配该变量。
一般来说,对一个在初始化后永远不会重新分配的变量使用 final
是一个很好的编程习惯。它提高了可读性,因为阅读你的代码的人都知道,如果不阅读完整的代码,这个变量也永远不会被重新分配。