Recently, I wrote a small crawler, which used multi-threading technology, suddenly found that this technology was somewhat strange, so I started to ask Du Niang crazily, and record it here, so that I and your small partners can learn.
I. What is Thread
An application is equivalent to a process. The process has all the resource processes of the application, including threads. The resources of the process are shared by threads, but not threads. We can turn on the task manager in the computer, running. exe is a process, the branches of which are threads.
II. Multithreading
Multithreading is actually a piece of code that runs in parallel in a process.
1. Create and start threads
1 static void Main() 2 { 3 //Getting threads Id 4 var threadId = Thread.CurrentThread.ManagedThreadId; 5 var thread = new Thread(Test1); 6 thread.Start(); 7 8 Console.WriteLine(threadId + "_Main()"); 9 Console.Read(); 10 } 11 12 /// <summary> 13 /// test method 14 /// </summary> 15 private static void Test1() 16 { 17 //Getting threads Id 18 var threadId = Thread.CurrentThread.ManagedThreadId; 19 Console.WriteLine(threadId + "_Test()"); 20 for (int i = 0; i < 10; i++) 21 { 22 Console.WriteLine(threadId + "_" + i); 23 } 24 }
Result:
2. Tentative Nogan Time of Threads
1 static void Main() 2 { 3 //Getting threads Id 4 var threadId = Thread.CurrentThread.ManagedThreadId; 5 var thread = new Thread(Test1); 6 thread.Start(); 7 Console.WriteLine($"Main thread Id{threadId}_Main()"); 8 Console.Read(); 9 } 10 11 /// <summary> 12 /// test method 13 /// </summary> 14 private static void Test1() 15 { 16 //Getting threads Id 17 var threadId = Thread.CurrentThread.ManagedThreadId; 18 Console.WriteLine($"Cothread Id{threadId}_Test()"); 19 for (int i = 0; i < 10; i++) 20 { 21 Thread.Sleep(1000);//Unit milliseconds 22 Console.WriteLine($"Cothread Id{threadId}_{DateTime.Now}"); 23 } 24 }
Result:
3. Thread merging
The Thread.Join operation blocks the current thread and waits for the sub-thread to complete before it runs.
1 static void Main() 2 { 3 //Getting threads Id 4 var threadId = Thread.CurrentThread.ManagedThreadId; 5 var thread = new Thread(Test1); 6 thread.Start(); 7 Console.WriteLine($"Main thread Id{threadId}_Main()1"); 8 thread.Join(); 9 Console.WriteLine($"Main thread Id{threadId}_Main()2"); 10 Console.Read(); 11 } 12 13 /// <summary> 14 /// test method 15 /// </summary> 16 private static void Test1() 17 { 18 //Getting threads Id 19 var threadId = Thread.CurrentThread.ManagedThreadId; 20 Console.WriteLine($"Cothread Id{threadId}_Test()"); 21 for (int i = 0; i < 10; i++) 22 { 23 Thread.Sleep(1000);//Unit milliseconds 24 Console.WriteLine($"Cothread Id{threadId}_{DateTime.Now}"); 25 } 26 }
Result:
4. Thread termination
1 static void Main() 2 { 3 //Getting threads Id 4 var threadId = Thread.CurrentThread.ManagedThreadId; 5 var thread = new Thread(Test1); 6 thread.Start(); 7 Console.WriteLine($"Main thread Id{threadId}_Main()1"); 8 Thread.Sleep(3000); 9 thread.Abort(); 10 Console.WriteLine($"Main thread Id{threadId}_Main()2"); 11 Console.Read(); 12 } 13 14 /// <summary> 15 /// test method 16 /// </summary> 17 private static void Test1() 18 { 19 //Getting threads Id 20 var threadId = Thread.CurrentThread.ManagedThreadId; 21 Console.WriteLine($"Cothread Id{threadId}_Test()"); 22 for (int i = 0; i < 10; i++) 23 { 24 Thread.Sleep(1000);//Unit milliseconds 25 Console.WriteLine($"Cothread Id{threadId}_{DateTime.Now}"); 26 } 27 }
Result:
5. Parametric Passing in Threads
1 static void Main() 2 { 3 //Getting threads Id 4 var threadId = Thread.CurrentThread.ManagedThreadId; 5 Console.WriteLine($"Main thread Id{threadId}_Main()"); 6 //The first way of parameter transfer 7 var thread1 = new Thread(() => Test1("Little Devil")); 8 thread1.Start(); 9 10 //The second way of parameter transfer(The parameter can only be one. object type) 11 var parameterizedThreadStart = new ParameterizedThreadStart(Test2); 12 var thread2 = new Thread(parameterizedThreadStart); 13 thread2.Start("The Great Devil"); 14 Console.Read(); 15 } 16 17 /// <summary> 18 /// test method 19 /// </summary> 20 private static void Test1(string name) 21 { 22 //Getting threads Id 23 var threadId = Thread.CurrentThread.ManagedThreadId; 24 Console.WriteLine($"Cothread Id{threadId}_My name is:{name}"); 25 } 26 27 /// <summary> 28 /// test method 29 /// </summary> 30 private static void Test2(object name) 31 { 32 //Getting threads Id 33 var threadId = Thread.CurrentThread.ManagedThreadId; 34 Console.WriteLine($"Cothread Id{threadId}_My name is:{name}"); 35 }
Result:
There are other modes of transmission, which are not explained here, but only introduced by Thread.
6. Thread Safety and Thread Lock
Thread security means that when multithreaded access, lock mechanism is adopted. When a thread accesses some data of this class, it protects it. Other threads can not access it until the thread has finished reading, other threads can not use it. In the case of thread security, there will be no data inconsistency or data contamination. Thread insecurity is not to provide data access protection, there may be multiple threads change the data one after another, resulting in dirty data! Generally speaking, the global variable is thread-safe if there are only read operations and no write operations for global variables and static variables in each thread; if multiple threads perform write operations at the same time, thread synchronization is generally considered, otherwise thread security may be affected.
The lock keyword marks the statement block as a critical area by acquiring the mutex of the specified object, executes the statement and releases the lock.
Lock ensures that when one thread is in the critical zone of the code, the other thread does not enter the critical zone. If other threads try to enter locked code, it will wait (that is, blocked) until the object is released. Using Lock will result in the serialization of the whole application, reduce the concurrency ability of the program and affect the performance.
In what scenario, lock is used to ensure thread safety: the serial is serial and the parallel is parallel.
Before locking:
1 public static int i = 1000000; 2 static void Main() 3 { 4 //Getting threads Id 5 var threadId = Thread.CurrentThread.ManagedThreadId; 6 for (int j = 0; j < 2; j++) 7 { 8 var thread = new Thread(Test1); 9 thread.Start(); 10 } 11 Console.Read(); 12 } 13 14 /// <summary> 15 /// test method 16 /// </summary> 17 private static void Test1() 18 { 19 //Getting threads Id 20 var threadId = Thread.CurrentThread.ManagedThreadId; 21 22 Console.WriteLine($"Cothread Id{threadId}_i Initial value:{i}"); 23 int count = 0; 24 for (int j = 0; j < 1000000; j++) 25 { 26 i--; 27 count++; 28 } 29 Console.WriteLine($"Cothread Id{threadId}_Number of runs:{count}"); 30 Console.WriteLine($"Cothread Id{threadId}_i End value:{i}"); 31 }
Result:
After locking:
1 public static int i = 1000000; 2 private readonly static object objLock = new object(); 3 static void Main() 4 { 5 //Getting threads Id 6 var threadId = Thread.CurrentThread.ManagedThreadId; 7 for (int j = 0; j < 2; j++) 8 { 9 var thread = new Thread(Test1); 10 thread.Start(); 11 } 12 Console.Read(); 13 } 14 15 private static void Test1() 16 { 17 //Getting threads Id 18 var threadId = Thread.CurrentThread.ManagedThreadId; 19 20 int count = 0; 21 lock (objLock) 22 { 23 Console.WriteLine($"Cothread Id{threadId}_i Initial value:{i}"); 24 for (int j = 0; j < 1000000; j++) 25 { 26 i--; 27 count++; 28 } 29 } 30 Console.WriteLine($"Cothread Id{threadId}_Number of runs:{count}"); 31 Console.WriteLine($"Cothread Id{threadId}_i End value:{i}"); 32 }
Result:
Well, today's knowledge about threads is sub-boxed here.