Dr. Strangelove
Dr. Strangelove

Reputation: 3338

Is it safe to r/w dictionary entries in a Parallel.ForEach in c#

I have a dictionary which I would like to modify it's values in a foreach loop, however, since my application is time critical, I'm trying to avoid all unnecessary locking overheads.

var loopData = new Dictionary<int, List<string>>();
var results = new Dictionary<int, List<string>>();

/// loopData and results are both initialized
/// with same set of keys.

Parallel.ForEach(loopData, data =>
    {
        var list = data.Value;
        /// manipulate list here

        /// Is this safe?
        results[data.Key] = list;
    });

Is the marked command safe to do? i.e., read/write to different key-value pairs of a dictionary without locking.

Note 1: I'm aware of concurrent collections namespace and all it's magnificent collections. Also I know that I can simply lock the highlighted command to ensure it's safety. As afore mentioned, my target is avoid unnecessary overheads as much as possible.

Note 2: a similar question is asked at this link. In that question the items of the container are modified inside the Parallel.ForEach loop. Whereas, here we are not modifying the key-value pairs, therefore the container is intact, only the data being pointed is changed. This makes it different from aforementioned question.

Update

  1. This code works fine with no locking, but I must be sure.
  2. Eventhough the ConcurrentDictionary would add least possible overhead, I would like to avoid it if this is safe.

Upvotes: 2

Views: 6823

Answers (2)

Thomas Weller
Thomas Weller

Reputation: 59641

From the comments I guess you have trouble understanding how many concurrent dictionaries you need. My annotations in code may help:

Parallel.ForEach(loopData, data =>
{
    var list = data.Value;       //<-- this is safe, because a read operation
    /// manipulate list here       <-- this is safe, because it operates on individual objects

    /// Is this safe?              <-- no, this is a write access
    results[data.Key] = list;
});

So you need only one concurrent dictionary, and that is for the results variable.

Upvotes: 1

Scott Chamberlain
Scott Chamberlain

Reputation: 127603

It is safe to read from the dictionary concurrently but it is not safe to write to it concurrently or read from it while writing concurrently. ConcurrentDictionary will be your fastest option for concurrent inserts.

Upvotes: 11

Related Questions