Reputation:
I have a list, lets say it does have 10 strings in it. I'll be launching threads, once a thread accesses an entry in list, I want pointer to move so when next thread wants to access it, it will access the next item. When we are at the bottom of list, pointer moves to top. Please advise on how I can do this. Threads won't be inserting anything, just reading and at runtime the string list won't change, its static.
Upvotes: 1
Views: 153
Reputation: 81563
You can use the lock statement
The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.
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;
}
}
}
Good comment by Christopher Pisz
I'd think it would be important to point out what needs to be locked and what doesn't and why. Will the OP take away that he needs to lock read only data? Should he? Is anything being written to? Is there a difference?
The lock
in this instance is forming a barrier around the read and in the index modifier. Both in this case are important.
The reason why is, both operations (in this case) need to be atomic (term used loosely). Meaning one read, and the associated modified index need to be done as one block and exclusive between all threads.
In another way, there is no point just locking the index modifications, as 2 threads could read the same value. Also and conversely, there is no point just locking the read, as 2 threads might have the same cached value of the index and will try to update it resulting in the wrong index.
Upvotes: 2
Reputation: 7111
How about something like:
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();
}
}
}
It compiles, but it's not very tested.
Upvotes: 0