Multithreading Study Notes 3rd
On the basis of the previous blog, this blog continues to record some knowledge about deadlocks, thread synchronization, and thread pools, so that I can continue to learn more and share it with you here.
1. Technical simulation of Object pool
(1) If the creation of some objects consumes a lot of time and resources, you can consider using the object pool technology.
(2) The object pool is actually an array. When we want to use an object, we can retrieve it directly from the pool. Other objects can also be retrieved from the pool.
(3) UseCodeAdd a lock in the demo of the simulated object pool
Namespace objectpoolpractice {class program {static void main (string [] ARGs) {// define an object pool myconnection [] Pool = new myconnection [100]; int Index = 0; // number of objects in the current Object pool // define a Lock Object object objlock = new object (); // you can lock the string, but try not to lock the string, because the reference to the same string is the same // Of course, this // can also be used to simulate the object pool, and the simulation by the producer and consumer // simulates five producers, keep adding the object for (INT I = 0; I <5; I ++) {thread = new thread () => {While (true) to the object pool) {// The lock object must be of the reference type, because the synchronized index block on the heap // only the same object can be locked for mutual exclusion lock (objlock) // blocking the current thread, wait for the lock {If (index <pool. length) {console. writeline ("produce an object"); // produce an object and place it in the pool. Producer myconnection conn = new myconnection (); // put it in the pool [Index] = conn; index ++;} // release the lock thread at the end of execution. sleep (300) ;}}); thread. isbackground = true; thread. start () ;}// simulate 10 Consumers for (INT I = 0; I <10; I ++) {thread = new thread (() ==>{ while (true) {lock (objlock) {If (index> 0) {console. writeline ("consume an object:" + pool [index-1]. tostring (); pool [index-1] = NULL; index --;} thread. sleep (30) ;}}); thread. isbackground = true; thread. start ();} console. readline () ;}/// assume that it takes a lot of time to create this object. Public class myconnection {}}
(4) database imitation lock
1) Select * from bank with (nolock) -- indicates that the current table is not locked during query.
(5) The solution to the deadlock is to operate resources in the same order.
2. Thread Synchronization
(1) refer to the above case code for instructions
(2) What did new do after applying for memory space on the stack?
1) object objlock = new object ();
2) Open up memory
3) Call Constructor
4) synchronize the block index (plural)
(3) Lock (syntactic sugar)
Try
{
System. Threading. Monitor. Enter (OBJ );
}
Finally
{
System. Threading. Monitor. Exit (OBJ );
}
(4) How does the lock code run? The lock statement basically uses monitor. enter and monitor. exit, that is, execute monitor when lock (o. enter (this). Execute monitor at the end of braces. exit (this ). what does it mean? For any object, the first part of the memory places the addresses of all methods, and the second part places an index, it points to a syncblock in the syncblock cache area of the CLR. what does it mean? That is to say, when you execute monitor. Enter (object), if the index value of the object is negative, select a syncblock from the syncblock cache and put its address in the index of the object. In this way, the object-marked locking is completed. If other threads want to perform the monitor. Enter (object) operation again, they will get the index with a positive number of objects, and then wait. Until the index changes to negative, that is, the thread uses monitor. Exit (object) to change the index to negative.
(5) Solve the Problem of thread synchronization: when multiple threads access the same resource at the same time, synchronize. At the same time, our resources can only be accessed by one thread.
3. Thread Pool
(1) InProgramIf the cost of creating an object is too high and this object can be used repeatedly, we will usually prepare a container to save a batch of such objects. Therefore, if we want to use such an object, we don't need to create one each time, but simply retrieve a ready-made object from the container. Because the cost of creating objects is reduced, the program performance naturally increases.
(2) threadpool class provides a thread pool that can be used to send work items, process asynchronous I/O, wait for other threads, and process timers. The thread pool allows multiple jobs to run in the background without the need to frequently create and destroy individual threads for each task, thus reducing the overhead.
(3) for common Windows applications (such as the console or winform/WPF), it is set to "processor count * 250 ". That is to say, if your machine has two 2-core CPUs, the maximum capacity of the CLR thread pool is 1000 by default. That is to say, it can manage up to 1000 threads to run simultaneously.
(4) waitcallback is a delegate type. The source code is as follows:
Public Delegate void waitcallback (Object State );
(5) thread pool demo
Static void main (string [] ARGs) {console. writeline ("main thread is:" + thread. currentthread. managedthreadid); // directly teach a method to the thread pool, and automatically execute the delegate method currently passed in when the threads in the thread pool are idle (INT I = 0; I <1000; I ++) {// generally, thread pools are used for asynchronous operations. In special cases, for example, when you have to get the instance of the current thread, then you can manually create a thread //. net uses thread pools in many aspects, such as Asynchronous delegation. As long as the threads allocated to us within the system are all provided through the thread threadpool in the thread pool. queueuserworkitem (New waitcallback (demowork), "Han Yinglong");} console. readline ();} Private Static void demowork (object state) {// This is the method console executed by the thread pool. writeline ("the thread of the method currently executed is: {0} + {1}", thread. currentthread. managedthreadid, state) ;}// you can run the following command to check whether the machine results of each user may be different.
(6) The thread pool supports a maximum of 1023 threads. The default value is 1000 and the minimum value is 0.
Static void main (string [] ARGs) {int maxthread = 0; int currentmaxtrhead = 0; threadpool. getmaxthreads (Out maxthread, out currentmaxtrhead); console. writeline ("the maximum number of threads is: {0}, the current setting is {1}", maxthread, currentmaxtrhead); // check the console with the smallest and largest threads. readkey ();} // The execution result is: the maximum number of threads is 1023, and the current setting is 1000.
(7) wait until the thread execution ends
Static void main (string [] ARGs) {int A = 0; thread = new thread () => {thread. sleep (3000); For (INT I = 0; I <10; I ++) {A ++;} console. writeline ("Han Yinglong") ;}); thread. isbackground = true; thread. start (); thread. sleep (1, 1000); thread. abort (); // tell the operating system to disable the thread. join (); // blocks the current thread and stops waiting for the thread to finish running the console. writeline (a); console. readline ();}
(8) work item
static void main (string [] ARGs) {// work item: A return value task
task = new task
(A => {return (INT) A ;}, 5) is added to the traditional thread pool. start (); // call the work item execution console. writeline (task. result); // The best thing about a task is to get the return value.}