1

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.

5
  • Lookup the C# lock keyword. You'll want to do you "move to the next item in the list, or to the beginning of the list if moving from the end" logic done within a lock block. Make sure that you use an instance of a reference type as the object upon which you base the lock (I always create a private lock object (of type object): private object _lock = new object(); and use it. Commented Dec 28, 2018 at 0:20
  • "I want pointer to move" seems problematic in managed C#....Can you think of and describe a mechanism to keep track of what elements is next? After that, tell us if it is read from or written to or both, by multiple threads. After that, consider Flydog's advice on locks and decide what gets locked. After that, show us some code and ask for help for more specific problems. Commented Dec 28, 2018 at 0:27
  • I don't really have to move the items in the list up and down, just the pointer/last use string from the list. So if I have "A", "B", "C" and thread1 took "A" and start working, thread2 will get B, thread 3 will get C, thread4 will get A and so on Commented Dec 28, 2018 at 0:29
  • The point I am making is that there are no pointers in managed C#. You'll have to use something else to keep track of which element is next to be "worked on", and then you'll have to make it threadsafe. Commented Dec 28, 2018 at 0:39
  • You may want to remove the word "Pointer" from your question title and body. Use something like "index" or a synonym instead. C# has the concept of unsafe pointers and that isn't what you are talking about. Commented Dec 28, 2018 at 0:50

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

8 Comments

@OracleJava Please note i forgot an = which should have been >=
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?
@ChristopherPisz indeed you don't need locking on essentially immutable array of strings. The only thing that needs locking here is "index". Note that you would not even need locking for writes to array as long as each thread only accesses its own region of the array (in this case single element).
@AlexeiLevenkov ahh ok i see what you mean, yes i agree.
@AlexeiLevenkov indeed once again this is very true. I mean passing the whole string to the thread would work as well, i guess it all depends what magical jar of wonderment the OP has developed and why
|
0

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.

2 Comments

Thank you, I'm going to use code from the other answer and since I don't have enough points, I can't upvote your answer, but thank you for providing a solution, I got the idea
The two solutions are equivalent. Mine's more wordy, but my emphasis (particularly with new coders) is to prefer clarity over elegance. What you want to do, though, is encapsulate all this in a class, making the lock, the index and the list of strings private. That way, no one can mess around (intentionally or inadvertently) with the behavior. As @ChristopherPisz pointed out, you want to minimize the scope of the locked code. My code is nearly all under lock, but often you end up with lots of code that isn't.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.