我正在开发一个学术开源项目,现在我需要在C#中创建一个快速阻塞FIFO队列.我的第一个实现只是在读者的信号量中包含一个同步队列(带有动态扩展),然后我决定以下面的方式重新实现(理论上更快)
public class FastFifoQueue<T>
{
private T[] _array;
private int _head, _tail, _count;
private readonly int _capacity;
private readonly Semaphore _readSema, _writeSema;
/// <summary>
/// Initializes FastFifoQueue with the specified capacity
/// </summary>
/// <param name="size">Maximum number of elements to store</param>
public FastFifoQueue(int size)
{
//Check if size is power of 2
//Credit: http://stackoverflow.com/questions/600293/how-to-check-if-a-number-is-a-power-of-2
if ((size & (size - 1)) != 0)
throw new ArgumentOutOfRangeException("size", "Size must be a power of 2 for this queue to work");
_capacity = size; …Run Code Online (Sandbox Code Playgroud) 我理解的功能Interlocked.Increment和lock().但我很困惑何时使用其中一个.据我所知,Interlocked.Increment增量共享int/long值,而as lock()则意味着锁定代码区域.
例如,如果我想更新字符串值,则可以使用lock():
lock(_object)
{
sharedString = "Hi";
}
Run Code Online (Sandbox Code Playgroud)
但是,Interlocked课程不可能实现这一点.
Interlocked?调用后检查溢出的正确方法是什么Interlocked.Increment?
我有一个 ID 生成器,可以在程序执行期间生成唯一的 ID,目前我测试增量是否返回零。
public static class IdGenerator {
private static int _counter = 0;
public static uint GetNewId() {
uint newId = (uint)System.Threading.Interlocked.Increment(ref _counter);
if (newId == 0) {
throw new System.Exception("Whoops, ran out of identifiers");
}
return newId;
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于我每次运行生成的 ID 数量相当大,(在异常大的输入上)_counter增量时可能会溢出,并且我想在这种情况下抛出异常(尽早崩溃以简化调试)。
摘自微软的文档:
location此方法通过包装: if =Int32.MaxValue,location + 1=来处理溢出情况Int32.MinValue。没有抛出异常。
我认为这种原子操作比快++.我只看到有利的优势Interlocked.Increment.它的不足之处是什么?
我希望两个线程与一个队列一起工作。第一个线程应该每2秒调用一次,第二个线程-每3秒调用一次。这两个线程应同时启动。访问队列的第一个元素时出现问题。两个线程都采用索引为0的元素。有时,它与队列的其他元素一起发生,而不仅仅是第一个元素。我在控制台上有这样的输出:
等等..
这是我使用的代码:
ConcurrentQueue<int> sharedQueue = new ConcurrentQueue<int>();
for (int i = 0; i < 10; i++)
{
sharedQueue.Enqueue(i);
}
int itemCount= 0;
Task[] tasks = new Task[2];
for (int i = 0; i < tasks.Length; i++)
{
// create the new task
tasks[i] = new Task(() =>
{
while (sharedQueue.Count > 0)
{
// define a variable for the dequeue requests
int queueElement;
// take an item from the queue
bool gotElement = sharedQueue.TryDequeue(out …Run Code Online (Sandbox Code Playgroud) 我试图了解Timer如何使用线程池.我写了以下简单的片段.
class Program
{
static private readonly Action Action = () => {
Thread.SpinWait(100 * 10000);
Interlocked.Increment(ref _data);
};
private static volatile int _data;
static private Timer _threadCountChecker = new Timer(
(obj) =>
{
var t = Process.GetCurrentProcess().Threads;
Console.WriteLine("Using {0} threads.", t.Count);
Console.WriteLine(Program._data);
}, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
static void Main(string[] args)
{
var l = new List<Timer>();
for (int i = 0; i < 10; i++)
{
l.Add(new Timer((obj) => Action(), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)));
}
var exitEvent = new ManualResetEvent(false); …Run Code Online (Sandbox Code Playgroud)