# 受控并发与原子性

1.7.1 七个实验接口、所有权、效果限制、事务与取消边界，以及可运行示例。

## 1.7.1 的范围与开启方式

默认生效：长期 Context 环境参与 GC roots；Stream 关闭释放负载引用；任务子进程独立配额失败恢复与清理；portable no-replace 使用独占发布。语言规范保持 1.0，Database 保持 1.0.0。

以下七个 API 是默认关闭的实验能力。HHY 采用同步 Runtime 和进程任务，没有新增协程调度器、async/await、共享内存 STM 或全局原子性。同一 HhyContext 不保证多线程并发调用安全。

```sh
HHY_CONCURRENCY_EXPERIMENTS=1 hhy run --engine bytecode atomic-state.hhy
HHY_CONCURRENCY_EXPERIMENTS=1 hhy run --engine ast atomic-state.hhy
hhy contracts --format json
```

上述变量只对单条命令生效。PowerShell 可先设置 $env:HHY_CONCURRENCY_EXPERIMENTS="1"，运行后 Remove-Item Env:HHY_CONCURRENCY_EXPERIMENTS。dry-run 只记录契约，返回 Null，不执行回调，也不验证真实结果。

## 原子性与一致性保证矩阵

| 资源域 | 提交与失败 | 边界 |
| --- | --- | --- |
| AtomicState | 所属 Runtime 同步发布整个候选值；提交前失败保留旧值 | 不跨 Runtime / Worker 共享 |
| 单文件 | 稳定 sidecar 锁内原子替换；发布后持久性可能未知 | 仅协作写者；不覆盖跨文件事务或网络文件系统 |
| 数据库 | 服务器 COMMIT；区分回滚与未知提交 | 隔离级别、SQL、约束和幂等共同决定一致性 |
| task_map | 全部成功后按序返回；失败终止并回收直接任务 | 不回滚子任务已发生的外部效果 |
| 普通变量 | 保持既有语义与隔离捕获 | 没有自动升级为原子变量 |

## 七个实验接口

- `atomic_state(data)` — 创建 Runtime/PID 所有者绑定的状态句柄。
- `atomic_read(state)` — 读取不可变快照。
- `atomic_update(state, callback)` — 校验纯回调候选值并同步发布；提交前错误保留旧值。
- `atomic_close(state)` — 关闭句柄；关闭后访问或再次关闭均失败。
- `atomic_file_update(path, timeout, callback)` — 锁内读改写已有普通文件；timeout 仅限制等锁时间。
- `transaction_strict(config, options?, callback)` — SQL 绑定当前 tx；捕获错误仍禁止提交；未知提交需对账。
- `task_map(data, parallelism, result_limit, callback)` — 隔离进程执行，按输入顺序返回 List，限制直接子任务和接收结果。

## 状态更新与句柄所有权

```hhy
let state = atomic_state({left: 0, right: 100})
fn transfer(old) { {left: old.left + 1, right: old.right - 1} }
atomic_update(state, transfer)
print(atomic_read(state))
atomic_close(state)
```

示例完成后 left 为 1、right 为 99。atomic_update 返回新值，atomic_read 读取不可变快照。数据只允许 Null、Bool、Int、有限 Float、String 和递归 List/Map，深度上限 128。Function、Stream 和句柄不允许进入状态。

AtomicState 绑定 Runtime/PID，不能 JSON 编码、传给任务或跨 Worker 捕获。每次访问检查 owner、PID、closed 和 busy；关闭后再次关闭也报错。提交前错误、取消或配额失败保留旧值，不自动重试。

## 效果契约与提交状态机

strict_capability 分为 pure、bound_transaction 和 external，白名单以 Runtime contracts 为准。严格回调禁止 I/O、任务、Stream、时钟、随机、import、变量赋值（包括局部 mut）和嵌套严格作用域。数据库回调额外允许绑定当前 tx 的 query/execute。第三方扩展不能自行声明 pure 绕过限制。

```text
ACTIVE -> COMMITTING -> COMMITTED
   |           |----> ABORTED
   |           `----> UNKNOWN
   `----> ABORTED
```

捕获回调错误仍会留下 rollback-only 状态，不能继续提交。Checker 提前拒绝直接闭包内已知违规调用，间接调用由 Runtime 验证；AST/Bytecode 共用提交内核，HIR/MIR 保留效果、异常和取消屏障。这不是全程序纯度证明。

## 单文件协作更新

```hhy
fn increment(text) { encode_json(to_int(text) + 1) }
atomic_file_update(path(args[0]), 3s, increment) |> print
```

```sh
printf '0' > /tmp/hhy-counter.txt
HHY_CONCURRENCY_EXPERIMENTS=1 hhy run atomic-file.hhy /tmp/hhy-counter.txt
```

文件必须预先存在；回调 String → String。等待锁的 Duration 须大于 0 且不超过 300s，不是回调执行期限。所有写者必须遵守同一路径和 <target>.hhy-lock 协议。拒绝符号链接、多硬链接和 .hhy-lock 目标名；活跃写者期间不要删除锁文件。不保证保留 inode、ACL 或扩展属性。

HHY_PUBLISHED_DURABILITY_UNKNOWN：替换已发布但目录持久性未知；HHY_PUBLISHED_CLEANUP_INCOMPLETE：no-replace 已发布但源清理未完成。不能把这些结果当成“未写入”盲目重试；进程崩溃或提交后资源耗尽也应重新读取业务状态。

## 受限数据库事务与持久幂等

```hhy
import database
let cfg = read_text(path(args[0])) |> parse_json
let n = cfg |> transaction_strict { tx ->
    database.execute(tx, "UPDATE counters SET n = n + 1 WHERE id = 1", [])
    return database.query(tx, "SELECT n FROM counters WHERE id = 1", []).rows[0].n
}
print(n)
```

先安装 Database 1.0.0 扩展，准备已有 counters 表及 id=1、n 为整数的记录，再以数据库配置 JSON 路径作为 args[0] 运行。配置遵循数据库扩展文档；凭据留在本地配置中。options 可设置已有 isolation/read_only。

回调不能使用其他 tx、连接池、流式句柄、手动 commit/savepoint，也不能返回 tx（包括嵌套结果）。MySQL 隐式提交语句被拒绝。服务器存储过程和触发器内部效果仍由服务器配置决定，Runtime 无法证明任意 SQL 无外部效果。

DB_COMMIT_UNKNOWN 不等于已回滚。使用同一事务内的唯一业务请求键与业务修改实现持久幂等，未知提交后按该键查询并对账。没有自动重试中间件，也没有数据库与文件/HTTP 的联合回滚。

[数据库安装与配置](DATABASE_1.0.0_README.md) — Database 独立版本 1.0.0

## 有界任务、取消与原 parallel

```hhy
let results = [1, 2, 3] |> task_map(2, 1mib) { n -> n * 2 }
print(results)
```

示例按输入顺序得到 [2, 4, 6]。task_map 接收 List 并急切返回 List，使用隔离子进程；parallel 保留已有 Stream 行为。并行度为正整数且受 Runtime 限额约束。结果预算为 1b–256mib，限制累计已接收的序列化结果。

每个子进程另有 RLIMIT_FSIZE；待接收文件总量可能达到并行度 × 结果限额，输入/输出 List 另受内存限额约束。后序任务失败可及时被发现；退出时向全部直接任务发 TERM，共享约 500ms 宽限后必要时 KILL 并回收。这不是实时保证，不保证清理脱离进程树的后代，也不回滚外部效果。

## 验收证据与仍未承诺的能力

- 本地 69 个引擎/配置用例；每引擎 10,000 次提交；GC、owner、配额与效果拒绝测试。
- 80 次竞争文件增量；native/portable no-replace 竞争；MySQL/PostgreSQL 32 请求、8 个幂等键及丢失提交回包对账。
- 120 秒长稳及 100,000 请求 Web 验收通过；不是 24 小时长稳、真实断电或通用共享内存线性化证明。
- 四平台 CI 与发行验收通过；Windows 为 MSYS2 工件，不包含 Database 扩展。
- HHY_BYTECODE_BINDING_CACHE=1 和 HHY_STREAM_SOURCE_FUSION=1 仍独立默认关闭；当前证据不支持默认开启或普遍加速声明。

[1.7.1 四平台 CI](https://github.com/hh696-wq/hhy-vm/actions/runs/34805271378) — f0fec9d · 2026-09-14

[真实数据库验收](https://github.com/hh696-wq/hhy-vm/actions/runs/34805271372) — MySQL / PostgreSQL

[1.7.1 发行说明与工件](https://github.com/hh696-wq/hhy-vm/releases/tag/v1.7.1) — 已发布；后续 1.7.x 候选仍按各自门槛推进
