Ensure real thread security-why does Microsoft not provide a thread security library?

Source: Internet
Author: User

Thread security is a very serious problem in the case of high concurrency. The following code may cause problems during multi-threaded access. The following uses list. add as an example to describe the situation of multi-threaded access. The following code is the implementation of list. Add.

public void Add(T item){    if (this._size == this._items.Length) this.EnsureCapacity(this._size + 1);    this._items[this._size++] = item;    this._version++;}

When two threads access the add method of a list at the same time, the first command of this method may be inconsistent. Because the _ size is the same when the two threads access the file. In the correct case, the List should execute ensurecapacity (this. _ SIZE + 2) instead of ensurecapacity (this. _ SIZE + 1. To ensure the thread security of the list, we must ensure that only one thread can be used to change the list data at any time. In this way, simplethreadsafelist is born. In this list, we add an exclusive lock to each of its read and write operations.

Public class simplethreadsafelist <t>: ilist <t>
{
Private list <t> _ data;
Private object _ syncroot = new object ();
Public simplethreadsafelist ()
{
_ DATA = new list <t> ();
}
Public void removeat (INT index)
{
Lock (_ syncroot)
{
_ Data. removeat (INDEX );
}
}
Public void add (T item)
{
Lock (_ syncroot)
{
_ Data. Add (item );
}
}
// Others ......
}

In this way, we ensure that the List data is accessed by only one thread at any time, and it looks much safer. However, if the so-called thread security is so simple, why does Microsoft not provide a threadsafelist? Jaredpar MSFT describes why are thread safe collections so hard? Bytes.

VaR list = new simplethreadsafelist <int> ();
// Ohters...
If (list. Count> 0)
{
Return list [0];
}

In the above Code, we created the simplethreadsafelist class. One of the code segments is the default value used to obtain the list. If multiple threads access this code, data inconsistency still occurs. That is, when the "return list [0]" statement is executed, it uses "list. count> 0. When two threads operate on this simplethreadsafelist simultaneously, the current thread accesses the list. count is greater than 0, but another thread may clear the list later. At this time, when the current thread returns list [0], indexoutofrangeexception will occur. Simplethreadsafelist ensures that only one thread can operate the internal data of the list, but it cannot guarantee data inconsistency for the above Code. Simplethreadsafelist can only be called "Data thread security", which is why Microsoft does not provide a thread security set class. Jaredpar
MSFT proposes a real solution to thread security. Expose the _ syncroot of simplethreadsafelist.

Public class simplethreadsafelist <t>: ilist <t>
{
Private object _ syncroot = new object ();
Public object syncroot
{
Get
{
Return _ syncroot;
}
}
// Others ......
}

When using list, you need to use syncroot to lock.

Lock (list. syncroot)
{
If (list. Count> 0)
{
Return list [0];
}
}

However, using this method has several drawbacks. First, there is no good guide to guide the compilation of thread-safe code. Second, when syncroot is used in a large range, it is very easy to cause a deadlock. Below is a piece of code that may cause deadlocks.

VaR list1 = new simplethreadsafelist <int> ();
VaR list2 = new simplethreadsafelist <int> ();

New thread () =>
{
Lock (list1.syncroot)
{
List2.add (10); // indirectly requested list2.syncroot
}
}). Start ();

New thread () =>
{
Lock (list2.syncroot)
{
List1.add (10); // indirectly requested list1.syncroot
}
}). Start ();

For the deadlock issue, we adopt monitor. tryenter to avoid deadlock. For the previous problem, I am only using disposablelocker to achieve thread security as much as possible. I still have no good theory about how to use it, we can only say that when designing highly concurrent APIs, We need to judge the objects that can be accessed by multiple threads at the same time to determine the method to be used for processing.

Namespace uishell. osgi. Collection
{
/// <Summary>
/// Use monitor. tryenter to acquire a lock. This wocould not cause the dead lock.
/// </Summary>
Public class disposablelocker: idisposable
{
Private object _ syncroot;
Private bool _ lockacquired;
Private int _ millisecondstimeout;
Public disposablelocker (Object syncroot, int millisecondstimeout)
{
_ Syncroot = syncroot;
_ Millisecondstimeout = millisecondstimeout;
_ Lockacquired = monitor. tryenter (_ syncroot, _ millisecondstimeout );
Logwhenacquirelockfailed ();
}
Private void logwhenacquirelockfailed ()
{
If (! _ Lockacquired) // at this time, it may take the following processing: (1) record the log; (2) record the log and throw an exception; (3) record the log, block it, and reproduce the deadlock.
{
Filelogutility. Error (string. Format (
"Accquire the lock timeout. The limited time is {0} milliseconds .",
_ Millisecondstimeout
));
}
}
Public void dispose ()
{
Dispose (true );
GC. suppressfinalize (this );
}
Private void dispose (bool disposing)
{
If (disposing)
{
If (_ lockacquired)
{
Monitor. Exit (_ syncroot );
}
}
}
~ Disposablelocker ()
{
Dispose (false );
}
}
}

When a deadlock occurs, the solution here is to record the log and continue running. However, this method has some drawbacks and may cause data inconsistency in extreme cases. Therefore, we may need to throw an exception or keep the lock going. Simplethreadsafelist will be implemented in the following way.

Public class simplethreadsafelist <t>: ilist <t>
{
Private object _ syncroot = new object ();
Public object syncroot
{
Get
{
Return _ syncroot;
}
}
Public int millisecondstimeoutonlock {Get; private set ;}
Public disposablelocker createlocker ()
{
Return new disposablelocker (millisecondstimeoutonlock, syncroot );
}
Public void add (T item)
{
Using (createlocker ())
{
_ Data. Add (item );
}
}
// Others ......
}

Next, use list. createlocker to create a global lock.

Using (list. createlocker ())
{
If (list. Count> 0)
{
Return list [0];
}
}

You can check whether there is a better way to ensure absolute thread security.

From Tao nature, blog Park

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.