19

据我所知,这java.util.Date是可变的,所以如果多个线程试图访问和修改它,它就不是线程安全的。我们如何使用客户端锁定或组合(包装器)使其成为线程安全的?

4

4 回答 4

36

按照这个顺序,从最好到最差:

  1. 根本不使用它,请查看 Java 8 的新 Date and Time API

  2. 根本不用,看看

  3. 根本不使用它,使用AtomicLong或不可变原语longvolatile表示纪元时间

  4. 封装它。总是返回防御性的副本Date,而不是对内部对象的引用

  5. Date在实例上同步。

于 2012-09-03T19:17:03.693 回答
4

您可以使用 long 值(自 Epoch 以来的毫秒数)而不是 Date 实例。分配它将是一个原子操作,并且始终是连贯的。

但是您的问题可能不在于 Date 值本身,而在于整个算法,这意味着真正的答案将基于您的实际问题。

这是多线程上下文中错误操作的示例:

long time;
void add(long duration) {
   time += duration; 
}

这里的问题是你可能有两个并行添加导致只有一个有效的添加,因为time += duration它不是原子的(它真的是time=time+duration)。

使用 long 而不是可变对象是不够的。在这种情况下,您可以通过将函数设置为同步来解决问题,但其他情况可能会更加棘手。

于 2012-09-03T19:18:16.357 回答
2

最简单的解决方案是永远不要修改 Date 并且永远不要共享它。即只对局部变量使用日期。

您可以使用 JodaTime,因为它具有不可变的日期对象。

于 2012-09-03T19:17:58.723 回答
-1

没有简单的解决方案来创建Date类的线程安全包装器。synchronized最好的方法是通过使用块来同步它的对象的所有用法。

于 2012-09-03T19:16:57.853 回答