In-depth understanding of the structure of. Net classes in memory and secure Thread Synchronization

Source: Internet
Author: User

I. Structure of the class in memory

Every time an object is created in the heap, each object obtains two additional overhead fields associated with it.

The first overhead field methodtablepointer contains the memory address of the method table of the type.
Basically, this pointer makes it possible to obtain information about the type of any object in the heap. In fact, when you call the GetType method of system. object internally, this method determines the object type according to the methodtablepointer field of the object.

The second overhead field is syncblockindex, which contains the 32-bit signed integer index cached by syncblock.

When an object is built, the syncblockindex of the object is initialized to a negative value, indicating that it does not reference any syncblock at all.
Then, when you call a method to synchronize access to this object, the CLR will find an available syncblock in its cache, and
Syncblockindex is set to reference this syncblock. In other words, when the object needs to synchronize fields, syncblock
Is instantly associated with this object. When there are no other threads to synchronize object access, the syncblockindex of this object is reset to a negative number, and syncblock
It can be used to associate with other objects in the future.

For a specific representation of this idea, see.

In
In the "CLR Data Structure" section of the figure, you can see that each type of data that the system knows has a data structure. You can also see the syncblock
Structure set. In the "managed heap" section of the figure, you can see that three objects are created: objecta, objectb, and objectc. The
The methodtablepointer field references the type of the method table. From this method table, you can know the type of each object. Therefore, we can easily see objecta
And objectb are sometype instances, while objectc is anothertype instances.

You will notice that the syncblockindex overhead field of objecta is set to 0. This indicates that syncblock #0 is currently used by objecta.
On the other hand, the syncblockindex field of objectb is set to-1, which indicates that objectb does not have a syncblock associated with it for use.
Finally, the syncblockindex field of objectc is set to 2, which indicates that it uses syncblock #2.
In my example, syncblock #1 is not used and may be associated with an object in the future.

Therefore, logically, you can see that each object in the heap has
Syncblock, which can be used for fast and exclusive thread synchronization. However, physically, only syncblock is required.
Structures are associated with objects. When they are no longer needed, they are unbound from objects. This indicates that the memory usage is very effective. By the way, if necessary
The syncblock cache can create more syncblocks, so if you want to synchronize many objects at the same time, you don't have to worry about the system will exhaust them.

Ii. Secure Thread Synchronization

In multi-thread programming, lock/synclock
Statement used to createCodeOnly the key or brief part of one thread is executed at a time. This statement locks the unique monitoring object associated with the object you specified. If other threads have locked the monitoring object
Wait. Once the monitoring object is locked, no other thread can lock the monitoring object. Unless your thread is unlocked, the unlocking will automatically happen at the end of the closed block. A common usage is locking
This/me reference, so that only your thread can modify the object you are using-
However, it is better to lock the specific object you are about to modify. The advantage of locking objects as small as possible is that it can avoid unnecessary waiting.

In C #, the locking method is lock (typeof (classname), where classname is the name of a class; in Microsoft Visual Basic. net, the locking method is synclock GetType (classname ).

GetType and typeof return references to type objects of this type. The system. Type type object contains methods that allow you to reflect the type. This means that you can find its fields and methods, or even access fields and call methods. Once you have a reference to a type object, you can create an instance of this object.

Therefore, the type object is very convenient. However, someProgramUsers like to abuse this method to replace static/shared
Object. (Unfortunately, in the C # document and Visual Basic. net
This method is mentioned in the document, suggesting that this is a recommended practice .) In this case, the suggestions in these documents are incorrect. This approach is unacceptable, let alone recommended.

The reason is: because all instances of a class have only one type object, the locking type object is equivalent to the static object contained in the locking class. As long as you lock all instances of the class, wait until other threads access any part of any instance, and then lock the access, so that you can safely access static members, without being disturbed by other threads.

This practice is indeed effective, at least in most cases. But it also has some problems: first, obtaining a type object is actually a very slow process (although most Programmers think this process
). Second, other threads in any class, or even other programs running in the same application domain, can access this type of object. Therefore, they may block you completely instead of locking type objects.
.

The basic problem here is that you do not own this type of object, and you do not know who else can access it. In general, relying on locking is not a bad practice for you to create and you do not know who else can access objects. This can easily lead to deadlocks. The safest way is to lock only private objects.

But there are more serious problems. In the current version of. net
In the Runtime Library, type objects are sometimes shared between application domains (but not between processes. (Normally this is fine, because they do not change .) This means that running in other application domains (but in the same
Another application in the process) may lock the type object you want to lock, and never release the type object, so that your application has a deadlock. In addition, the type can be easily obtained.
Object Access permission, because this object has a name-a fully qualified name of this type! Remember, lock/synclock
It will be blocked until it can be locked. Obviously, locking objects that can be locked by other programs or components is not a good practice and can lead to deadlocks.

Even if this type of object is unique in your application domain, this is still a bad practice, because any code can access a common type object, this causes a deadlock. If you
The components used in the program are not compiled by you. This is especially problematic. (Even lock (this)/synclock me
This problem may also occur because others may lock you. Even if this happens, the root cause of the problem may be easier to find than the deadlock caused by locking the type object, because your object is not a cross-application
Global available objects in the ordered domain .)

So what method should we use? Very simple: you only need to declare and create an object as the lock, and then use it instead of the type object for locking. Generally, In order to copy the semantics of the problematic code, you want this object to be static/Shared-of course, it should actually be private! In short, you can run the following problem code:

 
// C #
Lock (typeof (FOO) {// bad code! No! No! No!
// Statements;
}

'Vb. net
Synclock GetType (myclass) 'bad code! No! No! No!
'Statements
End synclock

Change to the following correct code:

// C #
Lock (someprivatestaticobject) {// good code!
// Statements;
}

'Vb. net
Synclock GetType (someprivatestaticobject) 'Good code!
'Statements
End synclock

Of course, you must already have a private static object to be locked (if you use the lock to modify the static object, you may already have one !) Or you must create one. (Make it a private pair
To prevent other classes from locking your objects .) Do not try to lock fields that are not of the reference (object) type, such
INT/integer. In this case, a compiler error occurs. If you do not have a private static object to lock, you may need to create a dummy object:

 
// C #
Class myclass {
Private Static object someprivatestaticobject = new object ();
// Methods of class go here -- can lock someprivatestaticobject
}

'Vb. net
Class myclass
Private shared someprivatestaticobject as new object
'Methods of class go here -- can lock someprivatestaticobject
End Class

You need to analyze each situation separately to ensure that no problem occurs, but the above techniques usually work.

Note: first, no code except the class can lock myclass. someprivatestaticobject, thus avoiding many deadlocks. Since deadlocks are the most difficult problem to find the root cause, it may be a good thing to avoid deadlocks.

Second, you know that your application only has one copy of myclass. someprivatestaticobject.
And each other application running on the system has only one copy. Therefore, applications in the same application domain do not affect each other. In short, do not lock the type object because you do not
I know where the problem occurs again. The process of locking type objects is very slow, and deadlock may occur. This is a bad programming habit. Instead, you should lock the static object in the object.

--------- Self-organizing (msdn)

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.