Concurrency <;cflock name="&引用&燃气轮机;使用示波器锁定保险箱&;结构?
使用命名锁(例如,密钥名称)同步对作用域和结构的特定密钥的读/写访问是否安全?我已经做了一段时间了,从来没有遇到过并发问题,但我正在编写一个服务器级缓存,我想确保基于名称的锁定在Concurrency <;cflock name="&引用&燃气轮机;使用示波器锁定保险箱&;结构?,concurrency,coldfusion,locking,Concurrency,Coldfusion,Locking,使用命名锁(例如,密钥名称)同步对作用域和结构的特定密钥的读/写访问是否安全?我已经做了一段时间了,从来没有遇到过并发问题,但我正在编写一个服务器级缓存,我想确保基于名称的锁定在服务器范围内是安全的。我担心底层的实现可能不是线程安全的,对不同密钥的并发访问可能会导致问题。ColdFusion中通过cflock实现的锁仅仅是线程安全的。它们控制哪些线程可以同时(并发)访问代码。这些锁不会影响Java的内在锁或同步的方法/语句。因此,cflock本身并不提供线程安全性 用户显示CF结构不使用Conc
服务器
范围内是安全的。我担心底层的实现可能不是线程安全的,对不同密钥的并发访问可能会导致问题。ColdFusion中通过cflock
实现的锁仅仅是线程安全的。它们控制哪些线程可以同时(并发)访问代码。这些锁不会影响Java的内在锁或同步的方法/语句。因此,cflock
本身并不提供线程安全性
用户显示CF结构不使用ConcurrentHashMap(请参阅注释),所以您必须显式使用它们:createObject(“java”,“java.util.ConcurrentHashMap.ConcurrentHashMap”).init()
请注意,ConcurrentHashMap是类型和大小写敏感的(而常规结构则不是)
好消息
ColdFusion中的结构本质上是线程安全的。下面是一个比较不安全Java HashMap和安全ColdFusion结构的示例:
首次运行时使用:
第二次运行时使用:
#s[键]#,
#结构键列表#
HashMap将抛出ConcurrentModificationException
,因为映射是由主线程访问的,而被“interrupter”线程修改的
但是,结构不会引发异常。它只返回1,2,A,B,C
,因为迭代器阻止访问,即导致“中断器”线程的写操作被延迟。迭代器完成后(循环结束),它将释放锁并修改结构。这就是为什么structKeyList()
也会立即返回新编写的键值对“C”:3
您可以在的官方Java文档中阅读更多关于并发映射访问的实现细节。但是请记住,ColdFusion可能使用ConcurrentHashMap的派生版本。您到底“害怕”什么?命名锁仅同步对相同命名锁的访问,而作用域锁锁定整个作用域/结构,而不管哪个线程尝试访问它。如果需要(服务器范围)缓存,最好使用cfcache
(Ehcache)和region
属性。@Alex Well我们所有使用server
作用域的代码都使用名称锁,并且密钥从不从一个名称锁重叠到另一个名称锁,我仍然怀疑在CF范围/结构中设置2个不相关的属性是否会导致并发问题(例如,条目大小的内部计算等)。感谢您指出cfcache,我会看一看,但同样的锁定问题也会出现在许多不同的场景中。@plalx-结构的底层实现不是线程安全的。由于命名锁不会锁定整个对象或方法,比如synchronized
,我可以想象应用于HashMaps的线程安全问题在这里也适用。@Alex-文档中哪里说结构是线程安全的?上次我检查时,结构在内部使用HashMap。缓存文档提到了ConcurrentHashMap,但是我没有发现任何关于结构的东西。Alex,通常你在钱上是对的,但是。。在这一点上我有不同意见:-)。这还不足以证明结构在内部使用ConcurrentHashMap。创建一个在循环中添加键的线程,并在该结构中进行迭代,它将抛出一个java.util.ConcurrentModificationException,并进行足够的迭代。@Ageax不,它不会抛出异常。在CF10和CF2018中都没有。我很确定你知道如何找出Adobe内部使用的是什么。这是Java,不是机器代码,如果你知道我的意思的话。是的,我的测试确实在CF2016中抛出了一个异常。我没有时间检查其他版本,所以他们可能改变了什么?例外情况,以及。。“标准”。。测试表明,CF2016在某些方面使用了HashMap,例如,WriteMap(structNew().values())代码>。如果我稍后有时间,我将在CF10和CF2018上试用,并将结果发回。下面的示例显示CF10和2016都会抛出异常,但不会抛出2018。对于struct.values(),CF10/2016使用在CF11中运行的java.util.HashMap$values@Alex Currenlty,据我所知,它们扩展了AbstractMap
,而没有使用ConcurrentHashMap
。修改时进行迭代确实会引发ConcurrentModificationException
。这种行为似乎在2018年有所改变,我猜他们的实现基于ConcurrentHashMap
(无法确认,还没有2018年)。希望我们不是在迭代值,在这种情况下基于名称的锁看起来很好。无法使用ConcurrentHashMap
,因为调用map.ComputeFabSent
时,CF闭包未强制转换为函数。我需要创建一个JavaCF适配器。
<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>