.net 函数,该函数始终返回序列中的下一个整数
我需要创建一个函数来获取1到60序列中的下一个整数。每次调用函数时,我都需要它从上一个值开始递增,并返回下一个数字作为结果。它也不能在两个连续调用中返回相同的整数。当计数达到60时,序列需要重置回1。我希望函数没有参数 我创建了一个函数,它使用缓存来存储返回的最后一个值,但我担心对该函数的并发调用可能无法像我预期的那样工作,2次调用可能会得到相同的整数 缓存阻塞是在这个实例中使用的正确方法,还是我没有考虑其他方法 另外,使用.NET3.5时遇到了问题,这是一个web应用程序.net 函数,该函数始终返回序列中的下一个整数,.net,vb.net,caching,.net,Vb.net,Caching,我需要创建一个函数来获取1到60序列中的下一个整数。每次调用函数时,我都需要它从上一个值开始递增,并返回下一个数字作为结果。它也不能在两个连续调用中返回相同的整数。当计数达到60时,序列需要重置回1。我希望函数没有参数 我创建了一个函数,它使用缓存来存储返回的最后一个值,但我担心对该函数的并发调用可能无法像我预期的那样工作,2次调用可能会得到相同的整数 缓存阻塞是在这个实例中使用的正确方法,还是我没有考虑其他方法 另外,使用.NET3.5时遇到了问题,这是一个web应用程序 我刚刚使用Sync
我刚刚使用SyncLock编写了这个函数。有什么我看不到的明显问题吗?我正在使用缓存保存最后返回的值
Private Shared Function GetNextNumber() As Integer
Dim o As Integer
Dim r As Integer
If Not Cache("NextNumber") Is Nothing Then
o = DirectCast(Cache("NextNumber"), Integer)
Else
Cache.Insert("NextNumber", 1, Nothing, Nothing, Nothing, Caching.CacheItemPriority.NotRemovable, Nothing)
End If
Dim lock As New Object
SyncLock lock
If o = 60 Then
r = 1
Else
r = o + 1
End If
Cache.Insert("NextNumber", r, Nothing, Nothing, Nothing, Caching.CacheItemPriority.NotRemovable, Nothing)
End SyncLock
Return r
End Function
在java中,我会使用原子整数。。。找到以下端口: Java代码片段:
public class Sequence {
private final AtomicInteger counter;
Sequence(int max) {
counter = new AtomicInteger(0);
this.max = max);
}
public int next() {
counter.compareAndSet(max,0);
return counter.getAndIncrement();
}
}
听起来您正在实现一个
IEnumerator
。这是一个开始的好地方。关于螺纹安全,该条款规定:
枚举器对集合没有独占访问权;因此,通过集合枚举本质上不是线程安全的过程。即使在同步集合时,其他线程仍可以修改该集合,这会导致枚举数引发异常。为了保证枚举期间的线程安全,您可以在整个枚举期间锁定集合,也可以捕获由其他线程所做的更改导致的异常
有关使用锁定创建线程安全的IEnumerator的示例,请参阅
现在,您的线程安全性是否要求每个线程使用自己的IEnumerator
或共享一个?我认为引用的CodeProject文章假设的是前者。后者可能很困难,因为MoveNext
和Current
在设计上是独立的操作。因此,在原子上锁定两者听起来像是一个设计挑战
幸运的是,Jon Skeet似乎有:)ASP.net缓存是线程安全的,但有可能两个线程同时访问同一对象 我建议看一下“ConcurrentQueue(Of T)类” 并发队列将阻止调用,直到原始调用完成。此外,因为每次删除一个项目时,它都是一个堆栈,所以只需将其推回到堆栈中,形成一个顺序循环 即: 端模块 这就是我在3.5中的做法:
Module Module1
Private _Stack As New Queue(Of Integer)
Sub main()
For i As Integer = 1 To 60
_Stack.Enqueue(i)
Next
Do While True
Debug.WriteLine(GetNext())
Loop
End Sub
Private Function GetNext() As Nullable(Of Integer)
Dim result As Integer
SyncLock _Stack
result = _Stack.Dequeue()
_Stack.Enqueue(result)
End SyncLock
Return result
End Function
终端模块这是共享功能吗?可以从多个线程同时调用它。我可以从您的担忧中推断出这一点,但您没有说。
属性解决了这个问题。它可能最终被多个线程调用。我现在正在研究
属性。根据MSDN上的定义判断,我认为ThreadStatic不是我们要寻找的:标记为ThreadStaticAttribute的静态字段在线程之间不共享。每个执行线程都有一个单独的字段实例,并独立地设置和获取该字段的值。如果在不同的线程上访问该字段,它将包含不同的值。我是否误解了这个问题?我愿意接受任何有效的解决方案。该函数将在我们的应用程序中全局使用,因此无论是单线程还是多线程,它都需要可靠。如果这有帮助的话,它是一个在线应用程序。@NinjaBomb:听起来你想要一个线程安全的单例对象,那么。每个线程没有单独的对象。那就是。。。如果Thread1请求一个数字,它将得到1。然后thread3请求,得到2。然后Thread1再次询问,它得到3。线程2请求,得到4。等等在这种情况下,推荐Jon Skeet博客中的链接帖子。唯一的区别是,当到达集合的末尾时,您不希望停止枚举。你想重置为1。抱歉,我刚刚编辑了这个问题,以注意我们在.Net 3.5上,所以我认为该类不可用。它不是…你可以使用普通队列(t)并将_Stack.Dequeue包装在SyncLock中SyncLock方法可能看起来像是一种方法。希望我今天可以测试它,并让您知道。到目前为止,在我们的测试中,synclock方法工作正常。
Module Module1
Private _Stack As New Queue(Of Integer)
Sub main()
For i As Integer = 1 To 60
_Stack.Enqueue(i)
Next
Do While True
Debug.WriteLine(GetNext())
Loop
End Sub
Private Function GetNext() As Nullable(Of Integer)
Dim result As Integer
SyncLock _Stack
result = _Stack.Dequeue()
_Stack.Enqueue(result)
End SyncLock
Return result
End Function