C # Programming Summary (V) Some thoughts of multithreading

Source: Internet
Author: User

C # Programming Summary (V) Some thoughts of multithreading

If there is something wrong, please criticize it.

1. When to use multithreading?

This problem, for system architects, designers, programmers, is the first to face a problem.

When do I use multithreaded technology?

In many common scenarios, multithreading can be used to significantly improve the responsiveness and availability of your application.

In the previous chapter, we talked about several multi-threaded application cases, and the main application scenarios were introduced. Don't repeat it here.

Http://www.cnblogs.com/yank/p/3232955.html

2. How can I ensure thread safety?

Using multi-threading, this is a problem that must be clarified. Only by understanding the impact of multithreading on structures and programs can you really use multi-threading to make it work as expected.

Why is it unsafe to apply multithreading?

A decision indicator of thread safety, there are no critical resources between threads, if there is a critical resource, and there is no reasonable synchronization mechanism, there will be multiple threads competing for a resource, and if multiple threads are not getting the required resources, a deadlock will occur. Deadlock, the thread will be deadlocked with each other, the system is stagnant, if the consequences are serious, it directly causes the system to crash. Common cases are: producer and consumer problems, philosophers dining problems, etc.

I make a simplification according to the question of dining philosophers: Two people to eat in a restaurant, because of resource constraints, only a pair of chopsticks, everyone is hungry, want to eat, and at the same time to rob chopsticks, evenly, two people each grab a chopstick, only use a pair of chopsticks to eat. At this time you will say, I can use my hands to eat, hehe. If it is just out of the pot dumplings, afraid you can't catch up. Two people can only looked at each other, at, is eat. If a a year is deadlocked, he will starve to death. Ha ha. If we give a contract, when taking chopsticks, get a pair, and after eating to exchange to each other. Then two of them were happily eating. Chopsticks are critical resources. Of course, when two people are deadlocked, external intervention is possible, allowing two of people to have food. For example: forcing one side to free the chopsticks, the other side on the meal. After eating the chopsticks free out, another person also has food to eat.

As long as we handle the critical resource problem, we also solve the problem of thread safety.

Using multiple threads does not necessarily require thread synchronization, but if there is a critical resource, thread synchronization must be done.

3. How can I write thread-safe code?

In OOP, programmers use nothing more than: variables, objects (properties, methods), types, and so on.

1) variables

Variables include value types and reference types.

The value type is thread-safe, but if the value type is attached to the object as a property of the object, you need to refer to the object's thread safety.

Reference type, it is important to note that for reference objects, he includes both the reference and the object instance, which need to be accessed by a reference to its storage location, for

Private object o = new Object (),

Can actually be broken down into two sentences:

Private Object o;

o = new Object ();

Where Private object o is a reference to a defined object, that is, a pointer to the object instance, not the object itself. This reference is stored on the stack and occupies 4 bytes, and when o = new Object () is not used, the value of the reference itself is null, that is, it does not point to any valid position, and when o = new Object () is actually allocated space in the managed heap to the object instance based on the size of the object, The pointer position of the instance is then assigned to the preceding reference. This completes the instantiation of an object.

The security of a reference type is that it can be referenced by multiple references while pointing to a memory address. If one reference is modified, the other is modified.

Using System;namespace variablesample{    class program    {        static void Main (string[] args)        {            Box B1 = New Box ();            B1. Name = "BigBox";            Console.WriteLine ("Create Box B1.");            Console.WriteLine ("Box:b1 ' Name is {0}.", B1. Name);            Console.WriteLine ("Create same box B2.");            Box b2 = B1;            B2. Name = "Littlebox";            Console.WriteLine ("Box:b2 ' s Name is {0}.", B2. Name);            Console.WriteLine ("Box:b1 ' s Name is {0}.", B1. Name);            Console.readkey ();        }    }    <summary>///box///    </summary> Public    class box    {        ///<summary> /////        </summary> public        string name        {            get;            Set;}}    }

Output Result:

Create Box B1. Box:b1 ' Name is bigbox.create same Box B2. Box:b2 ' s name is LITTLEBOX.BOX:B1 's name is Littlebox.

The change of the box name here is to modify the two reference object, in fact, we can design it as two multi-threading modification to the object. There must be a thread-safety problem here.

In summary, the thread safety of a variable is related to the scope of the variable.

2) Object

Object is an instance of a type

When you create an object, you have a separate memory area to store the properties and methods of the object. Therefore, multiple instances of a type, when executed, should be thread safe as long as there are no static variables involved.

This is not the same as our debug state. In debug state, if more than one thread creates an instance of an object, each object calls its own method, and in debugging, it discovers that the same code is accessed, and that multiple threads are in conflict. However, the real operating environment is thread-safe.

Take the salesman as an example, assuming the product is adequate, multiple salespeople, selling the product, calling method: Sale (), which is thread-safe.

However, if the warehouse is involved, the warehouse must have enough products to sell, at this time, multiple sales personnel have a critical resource: warehouse.

Here we discuss only the common methods of the object. As for the parameters passed in by the method, as well as the operation of static variables within the method, it is necessary to determine the thread safety of the method based on the parameters and static variables.

Salesman Case:

Using system;using system.threading;namespace mutithreadsample.sale{//<summary>//Sales//</summary&    Gt public class Saler {//<summary>/////</summary> public string Name {g Et Set        }///<summary>/////</summary> public int IntervalTime {get; set;}        <summary>///unit time sales volume///</summary> public int SaleAmount {get; set;} <summary>//Sales///</summary> public void Sale () {Console.Write Line ("Sales: {0} sold product {2}" at {1}, this. Name, DateTime.Now.Millisecond, this.            SaleAmount);        Thread.Sleep (IntervalTime); }//<summary>//Sales//</summary>/<param name= "Interval" > Time interval &LT;/PA ram> public void Sale (object obj) {whousethreadparameter parameter = obj as Whousethreadparam Eter if (parameter! = null) {while (parameter. Whouse! = null && parameter. Whouse.canout (this. SaleAmount)) {parameter. Whouse.outgoing (this.                    SaleAmount); Console.WriteLine ("Thread{0}, Sales: {1} in {2} sales out of stock product {3}", Thread.CurrentThread.Name, this. Name, DateTime.Now.Millisecond, this.                    SaleAmount); Thread.Sleep (this.                IntervalTime); }            }        }     }}

3) Type

An example of a class is already spoken--the object's multithreading security problem. Only static variables and static methods of the type are discussed here.

When a static class is accessed, the CLR invokes the class's static constructor (the type constructor), creates the type object of the static class, and the CLR wants to ensure that the type constructor is executed only once per application domain, in order to do this, when invoking the type constructor, the CLR adds a mutually exclusive thread synchronization lock for the static class, so If multiple threads attempt to invoke a static constructor of a type at the same time, only one thread can gain access to the static class, and the other threads are blocked. After the first thread finishes executing the type constructor's code and frees the constructor, the other blocked threads are woken up, and then the constructor is found to be executed, so these threads no longer execute the constructor, but simply return from the constructor. If you call these methods again, the CLR will realize that the type constructor has been executed and will not be called.

Calling a static method in a class, or accessing a static member variable in a class, is the same as the procedure above, so the static class is thread safe.

The simplest example is the database Operation helper class. The methods and properties of this class are thread-safe.

Using System;namespace mutithreadsample.static{public    class SqlHelper    {//                <summary>        // Database connection//        </summary>        private static readonly string ConnectionString = "";        <summary>///Execute database Commands///</summary>//        <param name= "SQL" >sql statements </param> Public        static void Excutenonquery (String sql)        {             //Perform data operations such as add, edit, delete}}}    

However, for static variables its thread safety is relative, and if multiple threads modify static variables, this is not necessarily thread-safe. The thread safety of static methods is directly related to the parameters passed in.

Anyway:

For variables, objects, types, said thread security, more general, here, mainly to let everyone understand, which places need to pay attention to thread security. For variables, objects (properties, methods), static variables, static methods, the thread security is relative and needs to be based on the actual situation.

Pierced, its judgment standard: whether there is a critical resource.

4. Is the collection type thread-safe?

Common collection types are list, Dictionary, HashTable, HashMap, and so on. In coding, where collections are widely used, common collections come from defining caches, and thread synchronization issues must be considered.

Collections are not thread-safe by default. There are only a few classes in the System.Collections namespace that provide the Synchronize method, which can create a thread-safe wrapper beyond the collection. However, all classes in the System.Collections namespace provide SyncRoot properties that can be used by derived classes to create their own thread-safe wrappers. The IsSynchronized property is also provided to determine whether the collection is thread safe. However, the ICollection generic interface does not provide synchronization capabilities, and non-generic interfaces support this functionality.

Dictionary (MSDN explained)

public static (shared in Visual Basic) members of this type are thread-safe. However, it is not guaranteed that all instance members are thread safe.
As long as you do not modify the collection, Dictionary<tkey, tvalue> can support multiple readers at the same time. Even so, enumerating through a collection from beginning to end is not inherently a thread-safe process. When there is a rare occurrence of contention between enumerations and write access, the collection must be locked during the entire enumeration. If multiple threads are allowed to perform read and write operations on the collection, you must implement your own synchronization.

Many collection types are similar to dictionary. By default, threads are unsafe. Of course Microsoft also provides thread-safe hashtable.

HashTable

Hashtable is thread-safe and can be used by multiple reader threads and one write thread. When multithreading is used, if only one thread is performing a write (update) operation, it is thread-safe, allowing no-lock read (if the writer is serialized as Hashtable). To support multiple writers, if no thread is reading the Hashtable object, all operations on Hashtable must be completed by the wrapper returned by the Synchronized method.

Enumerating through a collection from beginning to end is not inherently a thread-safe process. Even if a collection is synchronized, other threads can still modify the collection, which causes the enumerator to throw an exception. To ensure thread safety during enumeration, you can lock the collection during the entire enumeration, or catch exceptions that are thrown because of changes made by other threads.

For thread safety, use the following method to declare

        <summary>////  syncronized method used to create a new object for thread-safe packaging///        </summary>        Private Hashtable Hashtable = hashtable.synchronized (New hashtable ());

When enumerating reads, add lock, here Lock its synchronization object SyncRoot

        <summary>        ///Read        //</summary> public void Read ()        {             Lock (Hashtable. SyncRoot)            {                foreach (var item in Hashtable. Keys)                {                    Console.WriteLine ("Key:{0}", item);                }            }        }
5, how to thread synchronization?

In the third chapter has done the specific explanation, and introduced several commonly used thread synchronization method, the concrete visible:

Http://www.cnblogs.com/yank/p/3227324.html

6. IIS Multithreaded Application

IIS has multiple application pools, one for each w3wp.exe process, and one for multiple applications per application pool, one for each application domain, the application domain containing shared data and multiple threads, and a specified action in the thread. We can clearly understand the whole structure.

7, how to effectively use Multi-threading ?

Threads can greatly improve the usability and performance of the application, but multithreading also presents us with some new challenges, such as the need to use multi-threading and how to use multi-threading, depending on the actual situation.

1) Complexity

Using multi-threading can significantly increase application complexity, especially for thread synchronization and deadlock issues. You need to carefully assess where you should use multithreading and how to use multi-threading, so that you get the maximum benefit without creating unnecessarily complex and difficult-to-debug applications.

2) Quantity

Threads are not easy to do too much, and the number of threads is directly related to the server configuration (multicore, multiprocessor), and the process of business processing. Too little thread, can not fully play the processing power of the server, also can not effectively improve the processing efficiency of the transaction. Too much thread, and it takes a lot of time to thread control, and finally lose the candle. According to the actual situation, through the inspection test, set a specific reasonable range.

3) selection between synchronous and asynchronous invocations
Applications can either make synchronous calls or make asynchronous calls. The synchronous call waits for a response or return value before continuing. If the call is not allowed to continue, it says the call is blocked. Asynchronous or non-blocking calls do not wait for a response. An asynchronous invocation is performed by using a separate thread. The original thread initiates an asynchronous call, and the asynchronous call executes the request using another thread while the original thread continues processing.

4) selection between foreground thread and background thread
All threads in the. NET Framework are designated as foreground or background threads. The only difference between these two threads is that the background thread does not prevent the process from terminating. After all foreground threads that belong to a process are terminated, the common language runtime (CLR) ends the process, terminating any background threads that are still running.
By default, all threads generated by creating and starting a new thread object are foreground threads, and all threads from unmanaged code into the managed execution environment are marked as background threads. However, by modifying the Thread.IsBackground property, you can specify whether a thread is a foreground thread or a background thread. You can designate a thread as a background thread by setting Thread.IsBackground to True, and you can designate a thread as the foreground thread by setting Thread.IsBackground to False.

In most applications, you will choose to set different threads as foreground or background threads. In general, the thread that passively listens for activity should be set as a background thread, and the thread responsible for sending the data is set as the foreground thread, so that the thread will not be terminated until all the data has been sent. You should use a background thread only if you are sure that the thread is not adversely affected by the system's arbitrary termination. The foreground thread is used if the thread is performing a sensitive or transactional operation that must be completed, or if it needs to control how the thread is shut down in order to free important resources.

8. When to use thread pool (ThreadPool)?

Until now, you may realize that many applications benefit from multithreading. However, thread management is not just a matter of creating a new thread every time you want to perform a different task. Having too many threads can cause applications to consume unnecessary system resources, especially if there are a lot of short-running operations, all of which run on separate threads. In addition, explicitly managing a large number of threads can be very complex.
Thread pooling technology solves these problems by providing the application with a pool of worker threads that are managed by the system, allowing you to focus on application tasks rather than on thread management.
The thread can be added to the thread pool by the application, if needed. When the CLR initially starts, the thread pool does not contain additional threads. However, when the application requests threads, they are dynamically created and stored in the pool. If threads are not used for a period of time, these threads may be disposed of, so the thread pool is scaled down or expanded according to the requirements of the application.
Note: Each process creates a thread pool, so if you run several application domains within the same process, errors in one application domain can affect other application domains within the same process because they all use the same thread pool.

The thread pool consists of two types of threads:

    • worker Threads . Worker threads are part of a standard system pool. They are standard threads managed by the. NET Framework, and most features are executed on top of them.

    • complete the port thread . This thread is used for asynchronous I/O operations (by using the Iocompletionports API)

For each computer processor, the thread pool consists of 25 threads by default. If all 25 threads are in use, the attached request is queued until one of the threads becomes available. Each thread uses the default stack size and runs at the default priority level.

The following code example illustrates the use of the thread pool.

private void Threadpoolexample () {     WaitCallback callback = new WaitCallback (THREADPROC);     

In the preceding code, you first create a delegate that references the code that you want to execute in the worker thread. The. NET Framework defines a WaitCallback delegate that refers to a method that accepts an object parameter and does not have a return value. The following method implements the code that you want to execute.

private void ThreadProc (Object stateInfo) {     

You can pass a single object parameter to the ThreadProc method by specifying it as the second parameter in the QueueUserWorkItem method call. In the previous example, no arguments were passed to the ThreadProc method, so the stateInfo parameter was empty.

In the following case, use the ThreadPool class:

    • There are a large number of small independent tasks to perform in the background.

    • There is no need for fine-grained control of the thread used to perform the task.

Thread is displayed to manage threads. Whenever possible, you should use the ThreadPool class to create a thread.

In the following scenario, the Thread object is used:

    • A task with a specific priority is required.

    • It is possible to run a task for a long time (this may block other tasks).

    • You need to ensure that only one thread can access a specific assembly.

    • You need to have a thread-related stable identity.

C # Programming Summary (V) Some thoughts of multithreading

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.