-1

Imagine a ConcurrentDictionary storing a collection of Foo. Is it necessary to worry about thread safety for the Bar property of Foo (e.g. thread 1 getting value of Bar at same time thread 2 setting the value)? Or does the concurrency of the dictionary itself make the property thread safe?

//Bar with no lock
public class Foo
{
    public string Bar { get; set; }
}

//Bar with lock
public class Foo
{
    private readonly object barLocker = new object();
    private string bar;

    public string Bar
    {
        get
        {
            lock(barLocker)
            {
                return bar;
            }
        }
        set
        {
            lock(barLocker)
            {
                bar = value;
            }
        }
    }
}
philorube
  • 155
  • 8
  • Nobody could possibly comment on the functionality of code not shown. – Servy May 03 '17 at 21:38
  • This is a question about the ConcurrentDictionary object itself, not any specific implementation. – philorube May 03 '17 at 21:40
  • 3
    just because you are using a thread safe container that does not have any affect of the thread safety on the objects in the container. Once you retreive the object from the container you have a object – Scott Chamberlain May 03 '17 at 21:40
  • No, you're asking about an object being stored in a dictionary, and asking if usage of it is safe. Without knowing the object, how it's used, how the dictionary is used, and all of the other relevant context, nobody could possibly say if the usage is appropriate or not. – Servy May 03 '17 at 21:41
  • Nothing was mentioned about specific usage, as this is a general question about the ConcurrentDictionary itself and whether it provides thread safety for the properties of its contained objects. – philorube May 03 '17 at 21:43
  • @ScottChamberlain Thank you Scott. That's a great way to put it. Once I have the object, there's nothing stopping me from accessing/setting it's properties at will. – philorube May 03 '17 at 21:45

1 Answers1

1

Methods of the ConcurrentDictionary are threadsafe, but that does not extend to methods or properties of items in the dictionary.

Here's a unit test to demonstrate. It does the following:

  • Creates a string of forty 1s and 0s.
  • Creates a class with a string property and puts it in a concurrent dictionary.
  • Loops through all of the characters in the first string and appends each one to the property of the object that's in the dictionary.

If the ConcurrentDictionary made the object in it threadsafe then the new string property should at least be the same length as the original.

The result? The test passes once in a while but usually fails. The length of the string property is different from one test to the next because the property getting updated isn't threadsafe.

[TestClass]
public class ConcurrentDictionaryTests
{
    [TestMethod]
    public void DoesntMakeContentsThreadsafe()
    {
        var s = "1010101010101010101010101010101010101010";
        var dictionary = new ConcurrentDictionary<int, ClassWithProperty>();
        dictionary.TryAdd(1, new ClassWithProperty());
        Parallel.ForEach(s, c => dictionary[1].TheString += c);
        Assert.AreEqual(s.Length, dictionary[1].TheString.Length);
    }
}

public class ClassWithProperty
{
    public string TheString { get; set; }
}

Another way of looking at it - if putting an object in a ConcurrentDictionary made its properties threadsafe, it would be an easy fix for tons of multithreading properties. Need an object to be threadsafe? Just put it in a ConcurrentDictionary.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62