One of the most useful additions to the .Net 4.0 base class library is the System.Collections.Concurrent namespace, which contains an all-new set of lock-free thread.
However, these collections are noticeably different from their classical counterparts. There is no simple ConcurrentList<T> that you can drop into your code so that it will become thread-safe. Instead, the new namespace has a queue, a stack, and some new thing called a bag, as well as ConcurrentDictionary<TKey, TValue> that largely resembles classical dictionaries. It also has a BlockingCollection<T> class that wraps a concurrent collection and blocks until operations can succeed.
Many people have complained that Microsoft chose to provide an entirely new set of classes, rather than adding synchronized versions of the existing collections.
In truth, however, creating this new set of classes is the correct – and, in fact, only – choice. Ordinary synchronized are rarely useful and will not make a program thread-safe. In general, slapping locks everywhere does not make a program thread-safe! Rather, that will either not help (if there aren’t enough locks) or, if there are enough locks, result in deadlocks or a program that never runs more than one thread at a time. (depending on how many different objects get locked)
Collections in particular have two fundamental issues when used on multiple threads.
The first, and simpler, issue is that the collection classes themselves are not thread-safe. If two threads add to a List<T> at the same exact time, one thread is likely to overwrite the other thread’s value. A synchronized version of List<T> with a lock around every method would solve this problem.
The bigger issue is that any code that uses a List<T> is unlikely to be thread-safe, even if the list itself is thread-safe. For example. you can never enumerate over a multi-threaded list, because another thread may change the list at any time, invalidating the enumerator. This issue could be solved by taking a read lock for the lifetime of the enumerator. However, that is also a bad idea, since if any client code forgets to dispose the enumerator, the collection will deadlock when written to.
You also cannot use indices. It is never safe to get, set, or remove an item at an index, because another thread might remove that item or clear the entire collection between your index check and the operation.
To solve all of these problems, you need thread-safe collections that provide atomic operations. This is why all of the concurrent collections have such strange methods, including TryPop, AddOrUpdate, and TryTake. These methods perform their operations atomically, and return false if the collection was empty (as appropriate; consult the documentation for actual detail). Thus, the new concurrent collections can be used reliably in actual multi-threaded code without a separate layer of locks.
Other posts
-
A _read-only_ object is an object that does not expose any way to change it....
-
{% assign openTag = '{%' %} [Last time]({% post_url 2013-06-09-writing-about-jekyll-in-jekyll %}), we saw how to...
-
[Jekyll](http://jekyllrb.com) is a very nice system for writing blogs. However, it does have some shortcomings,...
-
The next step in [migrating my blog to Jekyll]({% post_url 2013-05-31-migrating-from-blogger-to-jekyll %}) was to convert...
-
The first step in my migration to Jekyll was to import my old posts into...
-
My new design is powered by Jekyll and LESS (the LESS does as much or...
-
After nearly a year of inactivity, I have finally returned to my blog. I had...
-
{% raw %} If you open an older ASP.Net MVC3 project in Visual Studio 2012,...
-
{% raw %} Last year, Microsoft announced a simple new feature in C# 5: Caller...
-
{% raw %} If you use the ASP.Net MVC 3 [Compare] validation attribute on a...
-
{% raw %} CSRF attacks are one of the many security issues that web developers...
-
{% raw %} What’s wrong with the following code? {% endraw %} {% highlight csharp...
-
{% raw %} One common misconception about web security is that protecting important actions with CAPTCHAs...
-
This post
-
ASP.Net MVC uses the new (to ASP.Net 3.5) Http*Base wrapper classes (HttpContextBase, HttpRequestBase, HttpResponseBase, etc)...
-
People sometimes wonder why C# 5 needs to add caller info attributes, when this information...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
One common question about ASP.Net MVC is how to make “default” controller. Most websites will...
-
Update: This bug was fixed in XRegExp 1.5.1. However, as far as I know, there...
-
Part 1 is here Some languages have better ways to pass boolean parameters. C# 4.0,...
-
Have you ever written code like this: public void UpdateLayout(bool doFullLayout) { //Code if (doFullLayout)...
-
C# is usually touted as a type-safe language. However, it is not actually fully type-safe!...
-
Until now, I've been focusing on only one of the differences between delegates and function...
-
When working with large .Net applications, it can be useful to find out where event...
-
A .Net event actually consists of a pair of accessor methods named add_EventName and remove_EventName. ...
-
Sometimes, it can be useful to make an extension method specifically for a single block...
-
Unlike WinForms or native Win32 development, WPF provides a rich layout model which allows developers...
-
This is part 5 in a series about state and function pointers; part 1 is...
-
This is part 4 in a series about state and function pointers; part 1 is...
-
.Net supports two kinds of delegates: Open delegates and closed delegates. When you create a...
-
This is part 3 in a series about state and function pointers; part 1 is...
-
This is part 2 in a series about state and function pointers; part 1 is...
-
Most languages – with the unfortunate exception of Java – allow functions to be passed...
-
Many people write ForEach extension methods for MVC WebForms views, which take a sequence and...
-
Razor’s inline helpers allow you to create lambda expression that return markup (as a HelperResult). ...
-
In addition to normal and static helpers, Razor supports inline helpers, (also known as templates),...
-
Razor helpers can be extremely useful, but they are designed to be used only by...
-
The Boot Camp drivers in the latest generation of MacBook Pros now expose more of...
-
We’ll continue our trek into Razor’s class-level features with helpers. Helpers are one of Razor’s...
-
After looking at how Razor’s Execute() method is generated, we will turn to class-level features....
-
Last time, we saw how basic Razor constructs are translated into C#. We can see...
-
After looking at the various assemblies in the WebPages framework, we will drill into the...
-
Last time, we saw how standalone Razor pages are served. MVC3 maintains the strict separation...
-
Last time, we saw that ASP.Net Web Pages are implemented in two independent assemblies. These...
-
Razor involves two distinct components: The Razor engine and the WebPages framework. The Razor engine,...
-
jQuery makes it very easy to modify a DOM tree. For example, to strip all...
-
Last time, we saw that there are severe limitations in creating ASPX pages which inherit...
-
ASP.Net pages can inherit from custom classes (as long as they inherit System.Web.UI.Page). This can...
-
.Net developers frequently need to build connection strings, especially when connecting to Access or Excel...
-
One of the unique features of ASP.Net WebPages (formerly Razor) is automatic HTML encoding. All...
-
C# 4.0 adds support for optional parameters. The following code prints 4: static void Main()...
-
The new ASP.Net WebPages view engine (formerly Razor) allows you to create reusable parameterized blocks...
-
.Net DataTables can be very useful when writing data-driven applications. However, they have one limitation:...
-
When designing fluent APIs, one issue that comes up is partial type inference. If a...
-
A common chore in developing real-world C# applications is implementing value semantics for equality. This...
-
Last time, we saw that the this parameter to an instance method in a struct...
-
Usually, you cannot pass ref this as a parameter, since this is not a writable...
-
VB.Net’s Nothing keyword is is not the same as C#’s null. MSDN states, “Assigning Nothing...
-
jQuery contains a powerful and flexible animation engine. However, it has some limitations, primarily due...
-
A generic class can specify that its generic parameter must inherit a type. However, there...
-
In part 1, we discussed the simple approach to making a nested iterator. However, we...
-
C# 2.0 introduced a powerful feature called an iterator, a method which returns an IEnumerable<T>...
-
My previous post stretched the limit of simple copy prevention. Beyond this point, it gets...
-
The methods discussed in my previous post are crude and ugly. Most of the time,...
-
Many web developers like to prevent their viewers from copying their text. While I do...