Multi-thread C # solution Summary
Two common problems related to multithreading need to be solved: critical resource protection and synchronization dependency between threads, each language provides its own set of facilities (some languages may need to use OS APIs) to solve these two problems. C # provides a more convenient and flexible solution, first, C # allows us to lock at different levels, that is, we can control the granularity of the lock. Second, C # provides a set of built-in thread-Safe Containers for our convenience.
1. synchronization at different levels:
1. Object level synchronization
The corresponding class must inherit from contextboundobject (synchronize the context so that all method calls can be intercepted) and
Use synchronizationattribute on the class.
2. Method level synchronization
Some attributes contained in the system. runtime. compilerservice space will affect the behavior of CLR during runtime. Features methodimplattribute can be used for synchronous control.
3. Code segment level synchronization
(1) monitor class (mainly static method)
Monitor. Enter (OBJ) // obtain the lock added to the object obj.
...
Monitor. Exit (OBJ) // release the lock
// The code between the above two sentences is equivalent to lock (OBJ ){...}
Monitor. tryenter (OBJ) // This method returns immediately. If the returned value is false, you do not need monitor. Exit (OBJ ).
// The following methods are used for inter-thread interaction = to solve synchronization dependency
Monitor. Wait (OBJ) // wait for the pulse message. Release the lock on the object and block the current thread. In the future, only when other threads call pulse or pulseall will they be given the opportunity to get the lock again.
Monitor. Pulse (OBJ) // transmits a pulse message (only after the lock is obtained can the message be fired, and the lock is not automatically released for the launch)
Monitor. pulseall (OBJ)
Note:
(1) The monitor locks the object and can only call wait and pulse in the code block between enter () and exit ().
(2) The lock cannot be obtained in one thread, but is released in another thread. This will cause lock loss. Obtaining and Releasing locks should be completed in the same thread.
(3) Lock statement
Lock (OBJ)
{
Code to be synchronized
}
(4) readerwriterlock class
Implement the lock for single-write and multi-read programs.
Acquirereaderlock () // you can obtain the lock when no program thread occupies the lock.
Acquirewriterlock () // The lock is obtained only when no read/write program thread occupies the lock.
Releasereaderlock ()
Releasewriterlock ()
(5) manualresetevent
Set () method to set the status to signal
Reset () to set it to no signal
Waitone () will be blocked until it has a signal. If there is a signal when waitone is called, it will not be blocked.
(6) autoresetevent
Unlike manualresetevent, autoresetevent. waitone () automatically changes the state of the event object, that is, every execution of autoresetevent. waitone () changes the state of the event once. Having a signal --> having no signal; having no signal --> having a signal
Note:
(1) Both monitor, lock, and readerwriterlock are valid only for objects of the reference type, because objects of the reference type have a hidden sync # field, this field is used as the lock mark.
(2) Among the above facilities, only the monitor and manualresetevent/autoresetevent can solve the synchronization dependency between threads, while other facilities are mainly used to solve the critical resource sharing.
4. member level synchronization
(1) interlocked class (mainly static method)
Synchronize a variable shared by many threads.
Decrement (ref INT); // subtract 1 from the variable
Increment (ref INT); // Add 1 to the variable
// The preceding two methods are only applicable to int-like variables.
Exchange (ref object, object );
(2) threadstaticattribute
This feature is used to modify static variables. Static variables modified by this feature have their own copies in each thread.
2. Create a thread-safe object
Hashtable H = hashtable. synchronized (New hashtable ());
Arraylist and other containers also provide similar operations.
C # multithreading notes (1)Document. Title = "C # multithreading notes (1)-" + document. Title
1. Each form has its own running on different threads. If you need to interact between forms, you need to interact between threads.
2. when the thread sleep, the system will exit the execution queue for a period of time. When the sleep ends, the system will interrupt the clock, so that the thread can return to the execution queue and resume the thread execution.
3. If the parent thread ends before the child thread, the Child thread is forced to end when the parent thread ends. The thread. Join () method waits for the parent thread until the child thread ends. The consequence of the abort () method is the unrecoverable termination thread.
4. The starting thread can be called the main thread. If all foreground threads are stopped, the main thread can be terminated, and all background threads will be terminated unconditionally.
There is only one difference between the background thread and the foreground thread, that is, the background thread does not prevent program termination. Once all the foreground threads of a process are terminated, CLR will completely terminate the process by calling the abort () method of any surviving background process.
6. Suspend, sleep (can be called-blocking, pause)
Unlike thread. Sleep, thread. Suspend does not stop the thread immediately. The thread can be suspended until it reaches the security point. If the thread is still
It cannot be suspended if it is not started or stopped. Calling thread. Resume will cause another thread to jump out of the pending state and continue the thread.
One thread cannot call sleep for another thread, but one thread can call suspend for another thread.
You can also use many other methods to block threads. For example, you can call thread. Join to make one thread wait for another thread (sub-thread) to stop. Use monitor. Wait to make a thread wait for access to a synchronization object.
5. the keyword lock can define a piece of code as a critical section. A mutex can be executed by only one thread at a time, while other threads must wait.
When multiple threads share an object, the lock keyword should not be used. Here, monitor and monitor provide a solution to share resources with threads.
The monitor class can lock an object. A thread can operate on this object only when this lock is obtained.
For example:
Monitor. Enter (OBJ );
// Currently, the oqueue object can only be manipulated by the current thread.
Monitor. Exit (OBJ );
6. A process starts with at least one main thread (that is, the main execution instance), which is the main execution flow created when the system loads your program.
The message queue is related to the thread. On a thread like Win2k, one queue corresponds to only one queue.
When is a message queue generated? On a Win2k system, the thread has been created from the very beginning.
One thread can create multiple forms. Messages sent to these windows are uniformly sent to the same message queue. Fortunately, the message structure contains MSG. hwnd indicates which window the message is related to. The dispatchmessage () function ensures that the message dispatching process is automated without errors!
7. Each form belongs to the thread that creates it. Directly accessing or indirectly asking the Form Method in other threads in the first line will lead to a runtime error (vs2005 ).
Solution: use the control. Invoke (delegate) method inherited from the form from control. This method executes the delegate pointing method on the thread that creates the form.
Note: In vs2003, you can directly or indirectly call the Form Method in another thread without causing runtime errors.
Reference announcement address: http://blog.csdn.net/zhuweisky/services/trackbacks/429826.aspx