我有一个列表,可以说它确实有10个字符串。我将启动线程,一旦线程访问列表中的条目,我希望指针移动,因此当下一个线程想要访问它时,它将访问下一个项目。当我们位于列表的底部时,指针将移至顶部。请告知我该怎么做。 线程将不会插入任何内容,只是读取,并且在运行时字符串列表不会更改,而是静态的。
答案 0 :(得分:2)
您可以使用lock statement
lock语句获取给定的互斥锁 对象,执行一个语句块,然后释放锁。而 持有锁后,持有锁的线程可以再次获取并 释放锁。任何其他线程被阻止获取锁 并等到锁被释放。
private static readonly object Sync = new object();
private int _index = 0;
private readonly List<string> _list = new List<string>() { "blah" ... };
...
public string SafeGetNext()
{
lock (Sync)
{
try
{
return _list[_index];
}
finally
{
_index = _index >= _list.Count - 1 ? 0 : _index + 1;
}
}
}
我认为指出什么需要锁定很重要 什么没有,为什么。 OP会带走他需要锁定的东西吗 只读数据?应该吗有什么东西要写吗?有没有 差异?
在这种情况下,lock
在读取周围和索引修饰符中形成障碍。在这种情况下,两者都很重要。
原因是,两个操作(在这种情况下)都必须是原子的(松散地使用)。意思是一次读取以及相关的修改后的索引需要作为一个块完成,并且在所有线程之间是互斥的。
以另一种方式,仅锁定索引修改没有意义,因为2个线程可以读取相同的值。同样,相反地,仅锁定读取是没有意义的,因为2个线程可能具有相同的索引缓存值,并且将尝试对其进行更新,从而导致错误的索引。
答案 1 :(得分:0)
怎么样?
public class StringListManager
{
private readonly object _lock = new object();
private readonly List<string> _theStrings = new List<string>();
private int _index = 0;
//maybe you want to do this in a constructor??
public void Initialize(IEnumerable<string> strings)
{
lock (_lock)
{
_theStrings.AddRange(strings);
}
}
public string GetNextString()
{
lock (_lock)
{
var count = _theStrings.Count;
if (count == 0)
{
return null; //or an empty string, your choice
}
var result = _theStrings[_index];
++_index;
if (_index >= count)
{
_index = 0;
}
return result;
}
}
public void ClearStrings()
{
lock (_lock)
{
_theStrings.Clear();
}
}
}
它可以编译,但是没有经过很好的测试。