2 回答
TA贡献1802条经验 获得超5个赞
第一个问题。
locks
在这种情况下,线程安全取决于对包含and buckets
(我们称之为)的对象的引用是否Container
被正确共享。
试想一下:一个线程正忙于实例化一个新Container
对象(分配内存、实例化数组等),而另一个线程开始使用这个半实例化的对象,其中locks
和buckets
仍然为 null(它们还没有被第一个线程实例化)。在这种情况下,这段代码:
synchronized (locks[bucketNum]) {
变得破碎并抛出NullPointerException
。关键字final
可以防止这种情况发生,并保证当对的引用不为空时Container
,其最终字段已被初始化:
当对象的构造函数完成时,该对象被认为已完全初始化。仅在对象完全初始化后才能看到对该对象的引用的线程保证能看到该对象的最终字段的正确初始化值。( JLS 17.5 )
第二个问题。
假设locks
和buckets
字段是最终的,并且您不关心整个数组的一致性,并且“每个存储桶 [i] 只在 lock[i] 下修改”,则此代码很好。
TA贡献2011条经验 获得超2个赞
在你问的第一个问题中
由于“桶”是最终的,因此即使没有同步,也不会有任何可见性问题。我的猜测是,通过同步,如果没有最终结果,也不会有任何可见性问题,这是正确的吗?
我不确定你所说的“可见性问题”是什么意思,但可以肯定的是,synchronized
如果多个线程访问buckets[i]
其中一个线程并修改它(例如写入它),那么如果没有这段代码,这段代码将是不正确的。无法保证一个线程所写入的内容对另一线程可见。这还涉及存储桶的内部结构,可能会通过调用来修改add
。
请记住,final
onbuckets
仅涉及对数组本身的单个引用,而不涉及其单元格。
添加回答
举报