软件事务内存的深入探索与实践
立即解锁
发布时间: 2025-08-19 02:34:05 阅读量: 2 订阅数: 34 


JVM并发编程的艺术与实践
# 软件事务内存的深入探索与实践
## 1. 提交和回滚事件
在事务处理中,我们常常需要根据事务的提交或回滚来执行不同的操作。Java 和 Scala 都提供了相应的机制来处理这些事件。
### 1.1 Java 中的提交和回滚事件
在 Java 中,我们可以使用 `StmUtils` 类的 `deferred()` 和 `compensating()` 方法来处理事务的提交和回滚事件。以下是一个示例代码:
```java
// Counter.java
public class Counter {
private final Ref<Integer> value = new Ref<Integer>(1);
public void decrement() {
new Atomic<Integer>() {
public Integer atomically() {
deferred(new Runnable() {
public void run() {
System.out.println("Transaction completed...send email, log, etc.");
}
});
compensating(new Runnable() {
public void run() {
System.out.println("Transaction aborted...hold the phone");
}
});
if(value.get() <= 0)
throw new RuntimeException("Operation not allowed");
value.swap(value.get() - 1);
return value.get();
}
}.execute();
}
}
// UseCounter.java
package com.agiledeveloper.pcj;
public class UseCounter {
public static void main(final String[] args) {
Counter counter = new Counter();
counter.decrement();
System.out.println("Let's try again...");
try {
counter.decrement();
} catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
```
运行上述代码,我们可以看到事务成功和失败时相应的代码块会被执行:
```plaintext
Transaction aborted...hold the phone
Transaction completed...send email, log, etc.
Let's try again...
Transaction aborted...hold the phone
Operation not allowed
```
### 1.2 Scala 中的提交和回滚事件
在 Scala 中,我们可以直接将闭包/函数值传递给 `deferred()` 和 `compensating()` 方法。以下是将 `Counter` 类从 Java 翻译到 Scala 的示例代码:
```scala
// Counter.scala
class Counter {
private val value = Ref(1)
def decrement() = {
atomic {
deferred { println("Transaction completed...send email, log, etc.") }
compensating { println("Transaction aborted...hold the phone") }
if(value.get() <= 0)
throw new RuntimeException("Operation not allowed")
value.swap(value.get() - 1)
value.get()
}
}
}
// UseCounter.scala
package com.agiledeveloper.pcj
object UseCounter {
def main(args : Array[String]) : Unit = {
val counter = new Counter()
counter.decrement()
println("Let's try again...")
try {
counter.decrement()
} catch {
case ex => println(ex.getMessage())
}
}
}
```
运行上述代码,输出结果与 Java 版本相同:
```plaintext
Transaction aborted...hold the phone
Transaction completed...send email, log, etc.
Let's try again...
Transaction aborted...hold the phone
Operation not allowed
```
### 1.3 提交和回滚事件处理总结
- **`deferred()` 方法**:适用于完成工作活动,使操作永久化,如打印、显示消息、发送通知、提交数据库事务等。
- **`compensating()` 方法**:适合用于记录失败日志。如果涉及到非托管对象,可在此处恢复操作,但建议避免这种设计,因为它容易出错。
## 2. 集合与事务
在处理事务时,我们需要确保所使用的值是不可变的,只有身份是可变的。同时,我们希望数据结构能够参与事务,其值不可变,但身份在管理的事务中可以改变。Akka 提供了 `TransactionalVector` 和 `TransactionalMap` 两种管理的数据结构。
### 2.1 Java 中使用事务性集合
以下是一个使用 `TransactionalMap` 记录玩家分数的示例代码:
```java
// Scores.java
public class Scores {
final private TransactionalMap<String, Integer> scoreValues = new TransactionalMap<String, Integer>();
final private Ref<Long> updates = new Ref<Long>(0L);
public void updateScore(final String name, final int score) {
new Atomic() {
public Object atomically() {
scoreValues.put(name, score);
updates.swap(updates.get() + 1);
if (score == 13)
throw new RuntimeException("Reject this score");
return null;
}
}.execute();
}
public Iterable<String> getNames() {
return asJavaIterable(scoreValues.keySet());
}
public long getNumberOfUpdates() { return updates.get(); }
public int getScore(final String name) {
return scoreValues.get(name).get();
}
}
// UseScores.java
package com.agiledeveloper.pcj;
public class UseScores {
public static void main(final String[] args) {
final Scores scores = new Scores();
scores.updateScore("Joe", 14);
scores.updateScore("Sally", 15);
scores.updateScore("Bernie", 12);
System.out.println("Number of updates: " + scores.getNumberOfUpdates());
try {
scores.updateScore("Bill", 13);
} catch(Exception ex) {
System.out.println("update failed for score 13");
}
System.out.println("Number of updates: " + scores.getNumberOfUpdates());
for(String name : score
```
0
0
复制全文
相关推荐










