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>