C # synchronized and syncroot implement source code analysis for thread synchronization and thread security access for generic Sets

Source: Internet
Author: User

Synchronized vs syncroot we know that in some set types of. net, such as hashtable and arraylist, there are both synchronized static methods and syncroot instance methods. Are there any relationships between them? How can I make good use of them?
Let's take hashtable as an example to see their basic usage:

Hashtable ht = hashtable. synchronized (New hashtable ());
Lock (HT. syncroot)
{
// Some operations
}

 

Synchronized indicates that a thread-safe hashtable is returned. What kind of hashtable is thread-safe? Next we will start to understand the source code of. net.
Public static hashtable synchronized (hashtable table)
{
If (Table = NULL)
{
Throw new argumentnullexception ("table ");
}
Return new synchashtable (table );
}
The source code shows that the Synchronized Method returns a synchhashtable instance. As we said before, synchronized indicates that a thread-safe hashtable is returned. From this explanation, synchhashtable should be inherited from hashtable. Let's verify it. Let's take a look at the source code of the synchhashtable type: Code
[Serializable]
Private class synchashtable: hashtable
{
// Fields
Protected hashtable _ table;

// Methods
Internal synchashtable (hashtable table): Base (false)
{
This. _ TABLE = table;
}

Internal synchashtable (serializationinfo, streamingcontext context): Base (Info, context)
{
This. _ TABLE = (hashtable) info. getvalue ("parenttable", typeof (hashtable ));
If (this. _ TABLE = NULL)
{
Throw new serializationexception (environment. getresourcestring ("serialization_insufficientstate "));
}
}

Public override void add (Object key, object value)
{
Lock (this. _ table. syncroot)
{
This. _ table. Add (Key, value );
}
}

Public override void clear ()
{
Lock (this. _ table. syncroot)
{
This. _ table. Clear ();
}
}

Public override object clone ()
{
Lock (this. _ table. syncroot)
{
Return hashtable. synchronized (hashtable) This. _ table. Clone ());
}
}

Public override bool contains (Object key)
{
Return this. _ table. Contains (key );
}

Public override bool containskey (Object key)
{
Return this. _ table. containskey (key );
}

Public override bool containsvalue (Object key)
{
Lock (this. _ table. syncroot)
{
Return this. _ table. containsvalue (key );
}
}

Public override void copyto (array, int arrayindex)
{
Lock (this. _ table. syncroot)
{
This. _ table. copyto (array, arrayindex );
}
}

Public override idictionaryenumerator getenumerator ()
{
Return this. _ table. getenumerator ();
}

Public override void getobjectdata (serializationinfo info, streamingcontext context)
{
If (Info = NULL)
{
Throw new argumentnullexception ("info ");
}
Info. addvalue ("parenttable", this. _ table, typeof (hashtable ));
}

Public override void ondeserialization (Object sender)
{
}

Public override void remove (Object key)
{
Lock (this. _ table. syncroot)
{
This. _ table. Remove (key );
}
}

Internal override keyvaluepairs [] tokeyvaluepairsarray ()
{
Return this. _ table. tokeyvaluepairsarray ();
}

// Properties
Public override int count
{
Get
{
Return this. _ table. count;
}
}

Public override bool isfixedsize
{
Get
{
Return this. _ table. isfixedsize;
}
}

Public override bool isreadonly
{
Get
{
Return this. _ table. isreadonly;
}
}

Public override bool issynchronized
{
Get
{
Return true;
}
}

Public override object this [object key]
{
Get
{
Return this. _ TABLE [Key];
}
Set
{
Lock (this. _ table. syncroot)
{
This. _ TABLE [Key] = value;
}
}
}

Public override icollection keys
{
Get
{
Lock (this. _ table. syncroot)
{
Return this. _ table. Keys;
}
}
}

Public override object syncroot
{
Get
{
Return this. _ table. syncroot;
}
}

Public override icollection values
{
Get
{
Lock (this. _ table. syncroot)
{
Return this. _ table. values;
}
}
}
}

Collapse Methods

 

Haha, as expected, synchashtable inherits from hashtable, and synchashtable can implement thread security operations because lock is added in some of their methods. We know that, which thread executes the lock operation. Before the lock is released, other threads are blocked. Synchashtable implements the so-called thread security through this method.

Now that we understand the meaning and usage of synchronized, let's take a look at its relationship with syncroot.
Syncroot indicates getting objects that can be used to synchronize hashtable access. To be honest, this explanation is hard to understand. To really understand its usage, we have to start from the source code: Public Virtual Object syncroot.
{
Get
{
If (this. _ syncroot = NULL)
{
Interlocked. compareexchange (ref this. _ syncroot, new object (), null );
}
Return this. _ syncroot;
}
}

If you are clear about the use of interlocked, this code is not hard to understand (if you are not clear about Google). Interlocked provides atomic operations for variables shared by multiple threads. An atomic operation is a single-threaded operation. In a hashtable instance, no matter where the code is called, all objects of the same object type are returned. The lock (HT. syncroot) We are writing has the same effect as the following operations.
Static object OBJ = new object ();
Lock (OBJ)
{
// Some operations
}
The difference between them is that the declared static object type objects are of Type level, while syncroot is of object level.

Through the above analysis, we should be able to understand synchronized and syncroot usage. The relationship between them is:
Hashtable generates a synchhashtable object through the synchronized method. In a method of this object, it uses lock (this. _ table. syncroot) code to implement thread-safe operations, where this. _ table. syncroot returns an object type object. In a synchhashtable object instance, it is unique no matter how many times we call it.

 

 

In addition, for thread-safe access to generic sets, the syncroot attribute is not directly published in the generic set, so it seems like you have no idea at all.

However, after viewing the source code of the Set generic set, we can find that they actually provide the syncroot attribute.

The following uses the queue <t> set as an example.

 

Bool icollection. issynchronized
{
Get
{
Return false;
}
}
 
Object icollection. syncroot
{
Get
{
If (this. _ syncroot = NULL)
{
Interlocked. compareexchange (ref this. _ syncroot, new object (), null );
}
Return this. _ syncroot;
}
}
 

From the source code above, we can see that both methods are implemented as private, but they can still be accessed using the icollection interface.

Lock (icollection) _ Queue). syncroot)
{
Int item = _ queue. dequeue ();
}

 

 

 

 

 

 

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.