<cflock name="..."> 使用作用域和结构锁定安全?

<cflock name="..."> locking safe with scopes & structs?

使用命名锁(例如键的名称)来同步 read/write 对作用域和结构的特定键的访问是否安全?我已经这样做了一段时间并且从未 运行 遇到并发问题,但我正在编写服务器级缓存并且我想确保基于名称的锁定在 server 范围内是安全的.恐怕底层实现可能不是线程安全的,并且对不同键的并发访问可能会导致问题。

通过 cflock 在 ColdFusion 中锁定只是 semaphores。它们控制哪些线程可以同时(并发)访问代码。这些锁不会影响 Java 的内部锁或同步 methods/statements。所以 cflock 本身不提供线程安全。

用户 Ageax 表明 CF 结构不使用 ConcurrentHashMap(见评论),因此您必须明确使用它们:createObject("java", "java.util.concurrent.ConcurrentHashMap").init()
请注意,ConcurrentHashMap 是类型和大小写敏感的(而常规结构不是)。

好消息

ColdFusion 中的结构本质上是线程安全的。下面是一个比较不安全的 Java HashMap 和安全的 ColdFusion Struct 的例子:

首先 运行 与:
<cfset s = createObject("java", "java.util.HashMap").init()>

第二个 运行 与:
<cfset s = structNew()>

<cfset s.put("A", 1)>
<cfset s.put("B", 2)>

<cfthread name="interrupter">
    <cfset s.put("C", 3)>
</cfthread>

<cfoutput>
    <cfloop collection="#s#" item="key">
        #s[key]#,
        <cfset sleep(1000)>
    </cfloop>
    #structKeyList(s)#
</cfoutput>

HashMap 将抛出 ConcurrentModificationException,因为映射在被 "interrupter" 线程修改时被主线程访问。

然而,Struct 不会抛出异常。它将简单地 return 1,2,A,B,C,因为迭代器阻止访问,即导致 "interrupter" 线程的写操作被推迟。迭代器完成后(循环结束),它释放锁并且结构将被修改。这就是为什么 structKeyList() 也会立即 return 新写入的键值对 "C": 3

您可以在 java.util.concurrent.ConcurrentHashMap 的官方 Java 文档中阅读更多关于并发地图访问的实现细节。但请记住,ColdFusion 可能使用 ConcurrentHashMap 的派生版本。