【发布时间】:2014-07-03 22:09:30
【问题描述】:
我正试图围绕 Java(或一般而言)中的线程安全。我有这个类(我希望它符合 POJO 的定义),它也需要与 JPA 提供程序兼容:
public class SomeClass {
private Object timestampLock = new Object();
// are "volatile"s necessary?
private volatile java.sql.Timestamp timestamp;
private volatile String timestampTimeZoneName;
private volatile BigDecimal someValue;
public ZonedDateTime getTimestamp() {
// is synchronisation necessary here? is this the correct usage?
synchronized (timestampLock) {
return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of(timestampTimeZoneName));
}
}
public void setTimestamp(ZonedDateTime dateTime) {
// is this the correct usage?
synchronized (timestampLock) {
this.timestamp = java.sql.Timestamp.from(dateTime.toInstant());
this.timestampTimeZoneName = dateTime.getZone().getId();
}
}
// is synchronisation required?
public BigDecimal getSomeValue() {
return someValue;
}
// is synchronisation required?
public void setSomeValue(BigDecimal val) {
someValue = val;
}
}
正如代码中注释行中所述,是否有必要将timestamp 和timestampTimeZoneName 定义为volatile,并且synchronized 块是否应按原样使用?或者我应该只使用synchronized 块而不将timestamp 和timestampTimeZoneName 定义为volatile? timestamp 的 timestampTimeZoneName 不应与另一个 timestamp 错误地匹配。
This 链接说
对于所有声明为 volatile 的变量,读写都是原子的 (包括 long 和 double 变量)
由于volatile 的定义,我是否应该了解通过setter/getter 访问此代码中的someValue 是线程安全的?如果是这样,是否有更好的(我不知道“更好”在这里可能意味着什么)方法来实现这一点?
【问题讨论】:
-
你打算使用
SomeClass作为JPA实体吗? -
是的,我将其用作 JPA 实体
-
EntityManager和@Entity类不应暴露于来自多个线程的并发访问。检查Transactions and Concurrency chapter from Hibernate docs。总而言之,我建议将同步应用于您的业务逻辑。 -
我想尝试从数据库中异步更新实体。就像工作线程定期刷新选择的实体一样。
标签: java multithreading synchronized volatile