Asp.net multi-thread programming (1/2)

Source: Internet
Author: User

For more information about how to implement multi-threaded data sharing in. net, see. net.

Data sharing between threads may result in a race rate and data inconsistency. For example:

The Code is as follows: Copy code
Namespace TaskParallel
{
Class Account
{
Public int Balance
{
Get;
Set;
}
}
Class Share
{
Static void Main (string [] args)
{
Account account = new Account {Balance = 0 };
List <Task> tasks = new List <Task> ();
For (int I = 0; I <10; I ++)
{
Tasks. Add (Task. Factory. StartNew () =>
{
For (int j = 0; j <1000; j ++)
Account. Balance ++;
}));
}
Task. WaitAll (tasks. ToArray ());
Console. WriteLine (account. Balance );
}
}
}

In this program, there are a total of 10 threads, each thread automatically adds an integer variable 1000 times, the expected result should eventually be 10000, however, the results of running this program are different each time and the total result is smaller than 10000. The reason is that the auto-increment of a variable is not an atomic operation. If you ignore the specific machine code, you should take three steps to read the current value, add 1, and save it back to the calculated value. if thread 1 reads the current value 0, it is replaced by thread 2 and enters the waiting state. Thread 2 reads the current value 0, adds 1, and stores 1 back, thread 1 then runs, add 1, and save 1. In this case, the Balance value is 1, and thread 1 and thread 2 have been added twice. data inconsistency occurs. The following describes the thread mutex method provided by. Net. Its implementation principles are described in detail in the operating system principles.

 

1. Use Monitor

To avoid inconsistency, ensure that only one thread is executing the code that can change the shared data at the same time. To achieve this, you can use the lock keyword of C:

The Code is as follows: Copy code
Object obj = new object (); for (int I = 0; I <10; I ++)
{
Tasks. Add (Task. Factory. StartNew () =>
{
For (int j = 0; j <1000; j ++)
{
Lock (obj)
{
Account. Balance ++;
}
}
}));
}

Lock is actually a packaging of the Monitor class. To use more complete functions, you can use the Monitor class. 2. Use Spin Locking.

The implementation of Spin Locking is similar to that of Monitor, but the principle is different. Spin Locking does not block the current thread, but uses a loop to constantly determine whether the access conditions are met. When the expected blocking time is not too long, it is more efficient than the Monitor class, but not suitable for cases that require long blocking.

The Code is as follows: Copy code
SpinLock locker = new SpinLock ();
For (int I = 0; I <10; I ++)
{Tasks. Add (Task. Factory. StartNew () =>
{
For (int j = 0; j <1000; j ++)
{
Bool lockAcquired = false;
Try
{
Locker. Enter (ref lockAcquired );
Account. Balance ++;
}
Finally
{
Locker. Exit ();
}
}
}));
}

3. Use Mutex and Semaphore

Mutex and Semaphore all inherit from the WaitHandle class and can implement thread Mutex. WaitHandle is the packaging of synchronization handles in windows.

First, we will introduce the Mutex example:

The Code is as follows: Copy code
Mutex mutex = new Mutex ();
For (int I = 0; I <10; I ++)
{
Tasks. Add (Task. Factory. StartNew () =>
{
For (int j = 0; j <1000; j ++)
{
Bool lockAcquired = mutex. WaitOne ();
Account. Balance ++; if (lockAcquired)
Mutex. ReleaseMutex ();
}
}));
}

WaitHandle's WaitAll method can obtain multiple locks at the same time. For example, in the following program, there are two accounts that need two locks to keep them only accessible by one thread at a time. The third thread Accesses both accounts at the same time. Therefore, you need to obtain the locks for the two accounts at the same time. When the third thread ends the access, remember to release the two locks.

 

The Code is as follows: Copy code

Using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Using System. Threading;
Using System. Threading. Tasks;

Namespace TaskParallel
{
Class Account
{
Public int Balance
{
Get;
Set;
}
}
Class Share
{
Static void Main (string [] args)
{
Account account1 = new Account {Balance = 0 };
Account account2 = new Account {Balance = 0 };
Mutex mutex1 = new Mutex ();
Mutex mutex2 = new Mutex ();

Task t1 = new Task () =>
{
For (int I = 0; I <1000; I ++)
{
Bool locked = mutex1.WaitOne ();
Account1.Balance ++;
If (locked)
Mutex1.ReleaseMutex ();
}
});

Task t2 = new Task () =>
{
For (int I = 0; I <1000; I ++)
{
Bool locked = mutex2.WaitOne ();
Account2.Balance ++;
If (locked)
Mutex2.ReleaseMutex ();
}
});

Task t3 = new Task () =>
{
For (int I = 0; I <1000; I ++)
{
Bool locked = WaitHandle. WaitAll (new WaitHandle [] {mutex1, mutex2 });
Account1.Balance --;
Account2.Balance --;
If (locked) // release two locks
{
Mutex1.ReleaseMutex ();
Mutex2.ReleaseMutex ();
}
}
});

T1.Start ();
T2.Start ();
T3.Start ();
Task. WaitAll (t1, t2, t3 );
Console. Write ("Balance1: {0}, Balance2: {1}", account1.Balance, account2.Balance );
Console. ReadLine ();
}
}
}

1 2

Related Article

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.