 |
Applications cannot avoid multithreaded environments anymore |
|
Web applications and event driven windows
applications are now inherently multithreaded. With the proliferation of low
cost web servers and hyper-threading chips on the desktop,
applications can no longer avoid parallel processing environments.
|
|
|
 |
Most developers are unaware of multithreading issues |
|
Multithreading concepts were traditionally in
the hands of senior C++ developers. .NET has changed that by putting
multithreading capabilities in the hand of every developer including VB and web
page developers. The simple process of creating a global variable creates
multithreading issue that many developers never conside.
|
|
|
 |
Threading bugs are hard to find and unpredictable |
|
Threading bugs can be one of the most obscure
bug types to find. They only appear in parallel processing environments whey
just the right timing and sequence of events occurs. Most only see these
problems when the code reaches production and cannot reproduce them in test
environments.
|
|
|
 |
Avoid deadlocks to create stable applications |
|
Deadlocks are fatal to an application causing
them to hang permanently and require killing of processes or threads to
recover. The devAdvantage threading rules help identify areas of potential
deadlocking early in the development cycle where the cost to fix them is
trivial.
|
|
|
 |
Eliminate race conditions and protect data from corruption |
|
When shared resources are not synchronized in a
multithreaded application there is a risk of invalid logic and data integrity
issues. devAdvantage helps developers quickly identify and fix code that needs
proper thread synchronization.
|
|
|
 |
Optimize multithreaded code and increase scalability |
Synchronizing shared data in a multi-threaded environment can
be dangerous if done incorrectly or too often.
Synchronization creates safe access to shared data by allowing only one
thread at a time to access the data (serialization of the operation).
This results in a potential bottleneck which can impact an applications
scalability and performance. devAdvantage
locates areas of excessive synchronization and opportunities for refactoring
code more effectively.
|
|
|
The threading knowledge pack contains threading rules based on
Microsoft’s C# Threading Design Guidelines
and other industry best practices.
Rule
|
Description
|
Automatic Correction
|
Reference to a static variable should be
synchronized using a thread lock.
|
Static members are shared across object instances and threads and should be
protected using some form of data synchronization (lock,
Monitor.Enter/Monitor.Exit, Synchronized methods, Interlocked methods,
synchronization attributes, etc.). This rule detects unsafe operations on
shared data and provides synchronization.
|
Yes
|
The update of a variable should be synchronized
using Threading.Interlocked operations.
|
Unprotected integer and long references should be synchronized using the
Interlocked methods such as Interlocked.Increment(), Interlocked.Decrement()
and Interlocked.Exchange().
|
Yes
|
Redundant Locking exists.
|
Interlocked operations are already effectively synchronized. There is no need
to synchronize a variable operation that is protected with the Interlocked
class, with and additional lock statement.
|
Yes
|
Optimize the update synchronization of a
variable by using Threading.Interlocked operations instead of a lock.
|
The Interlocked methods for locking single operations on integers and longs is
more efficient than a lock statement.
|
Yes
|
A logical block of unsynchronized static
variable references has been detected and should be synchronized using a lock.
|
More than just a single unprotected reference exists and requires synchronizing
the chain of logical operations.
|
Yes
|
Releasing a lock in any other location than a
'finally' section of try/finally block may create threading issues.
|
Using a try/finally block ensures that locks managed using Monitor.Enter and
Monitor.Exit are performed once and only once in all situations.
|
Yes
|
The released lock was not the last lock
acquired. Locks acquired last should be released first.
|
Locks using Monitor.Enter() and Monitor.Exit() should always be released in the
reverse order they were acquired. Incorrect order of acquiring and releasing
locks is one of the major causes of deadlock scenarios in a multi-threaded
application.
|
No
|
A lock on the same object has already been
acquired.
|
There is typically no good reason to perform multiple locks on one object
within the same thread using. If multiple locks are acquired within the same
thread using Monitor.Enter(), then the same number of releases must be issued
with Monitor.Exit(). This type of situation is indicative of deadlock
scenarios.
|
No
|
A lock has been acquired but has not been
released.
|
Acquiring a lock Monitor.Enter() and not releasing it with Monitor.Exit() is a
series bug that creates a deadlock situation. Address this issue by safely
releasing the lock when complete by using a Monitor.Exit with a try/finally
block.
|
No
|
A lock has been released in multiple places.
|
If locks are being released using Monitor.Exit() in multiple locations it is a
sign that the Monitor class may not be being used safely. If a lock is called
for release after it has already been released a SynchronizedLockException will
be thrown.
|
No
|
Avoid calling static methods that call static
methods on the same class.
|
Performance and scalability issues can result when a static method in class
calls another static method in the same class.
|
No
|
Avoid providing static methods that alter static
state.
|
In general, it is a weak design practice to be updating static data frequently
within a threaded application because of the need for synchronization. Altering
static state from a static method increases this likelihood.
|
No
|
Use thread pooling classes to optimize
multi-threaded applications.
|
Avoid using System.Threading.Thread class to create threads unless you have
special needs such as managing thread priority. Instead usage of system thread
pool (ThreadPool.QueueUserWorkItem) can improve your performance and
scalability.
|
No
|
Do not terminate other threads using
Thread.Abort.
|
Thread.Abort raises a ThreadAbortException. When called within a thread the
action is very predictable, but when called on a thread externally, the effect
may interrupt the processing anywhere - such as within a finally block. Use
Thread.Join to wait until desired thread finishes.
|
No
|
Lock Must not be Obtained on a Value Type.
|
Montor.Enter() and Exit() calls must lock on an object of a reference type.
They should never lock on an object of a value type such as object of type
"int". Unlike the lock statement, the compiler will allow you to acquire a lock
on an object of a value type.
|
No
|
Excessive locking - lock contained inside a
loop.
|
Excessive locking or thread synchronization can cause significant scalability
and performance issues in some applications and should be minimized. Locks
inside a loop indicate the potential for excessive locking.
|
No
|
Large number of statements protected by a lock.
|
Excessive locking or thread synchronization can cause significant scalability
and performance issues in some applications and should be minimized. The more
statements a lock contains, the more likely it is to impact scalability.
|
No
|
Excessive nesting of locks.
|
Excessive locking or thread synchronization can cause significant scalability
and performance issues in some applications and should be minimized. Nested
locks mean multiple locks are occurring and are also the root of most
deadlocking scenarios.
|
No
|
Excessive portion of class is synchronized.
|
Excessive locking or thread synchronization can cause significant scalability
and performance issues in some applications and should be minimized. If a large
portion of a class is synchronized it indicates that most references to the
class will require synchronization and potentially impact scalability.
|
No
|
Excessive synchronized calls into same class.
|
Excessive locking or thread synchronization can cause significant scalability
and performance issues in some applications and should be minimized. Method
calls into the same class that synchronization occurs can be an indication of
excessive synchronization.
|
No
|