Text version of the video
Slides
All C# Text Articles
All C# Slides
All Dot Net and SQL Server Tutorials
In this video we will discuss,
1. What happens if shared resources are not protected from concurrent access in multithreaded program
2. How to protect shared resources from concurrent access
What happens if shared resources are not protected from concurrent access in multithreaded program
The output or behaviour of the program can become inconsistent if the shared resources are not protected from concurrent access in multithreaded program. Let us understand this with an example.
using System;
class Program
{
static int Total = 0;
public static void Main()
{
AddOneMillion();
AddOneMillion();
AddOneMillion();
Console.WriteLine(“Total = ” + Total);
}
public static void AddOneMillion()
{
for (int i = 1; i [= 1000000; i++)
{
Total++;
}
}
}
The above program is a single-threaded program. In the Main() method, AddOneMillion() method is called 3 times, and it updates the Total field correctly as expected, and finally prints the correct total i.e 3000000.
Now, let’s rewrite the program using multiple threads.
using System;
using System.Threading;
class Program
{
static int Total = 0;
public static void Main()
{
Thread thread1 = new Thread(Program.AddOneMillion);
Thread thread2 = new Thread(Program.AddOneMillion);
Thread thread3 = new Thread(Program.AddOneMillion);
thread1.Start();
thread2.Start();
thread3.Start();
thread1.Join();
thread2.Join();
thread3.Join();
Console.WriteLine(“Total = ” + Total);
}
public static void AddOneMillion()
{
for (int i = 1; i [= 1000000; i++)
{
Total++;
}
}
}
Every time we run the above program, we get a different output. The inconsistent output is because the Total field which is a shared resource is not protected from concurrent access by multiple threads. The operator ++ is not thread safe. There are several ways to fix this. Let’s explore 2 of the options.
Using Interlocked.Increment() method: Modify AddOneMillion() method as shown below. The Interlocked.Increment() Method, increments a specified variable and stores the result, as an atomic operation
public static void AddOneMillion()
{
for (int i = 1; i [= 1000000; i++)
{
Interlocked.Increment(ref Total);
}
}
The other option is to use a lock.
static object _lock = new object();
public static void AddOneMillion()
{
for (int i = 1; i [= 1000000; i++)
{
lock (_lock)
{
Total++;
}
}
}
Which option is better?
From a performance perspective using Interlocked class is better over using locking. Locking locks out all the other threads except a single thread to read and increment the Total variable. This will ensure that the Total variable is updated safely. The downside is that since all the other threads are locked out, there is a performance hit.
The Interlocked class can be used with addition/subtraction (increment, decrement, add, etc.) on and int or long field. The Interlocked class has methods for incrementing, decrementing, adding, and reading variables atomically.
The following code prints the time taken in ticks. 1 millisecond consists of 10000 ticks.
public static void Main()
{
Stopwatch stopwatch = Stopwatch.StartNew();
Thread thread1 = new Thread(Program.AddOneMillion);
Thread thread2 = new Thread(Program.AddOneMillion);
Thread thread3 = new Thread(Program.AddOneMillion);
thread1.Start();
thread2.Start();
thread3.Start();
thread1.Join();
thread2.Join();
thread3.Join();
Console.WriteLine(“Total = ” + Total);
stopwatch.Stop();
Console.WriteLine(“Time Taken in Ticks = ” + stopwatch.ElapsedTicks);
}
Please Note: You can use the TimeSpan object to find ticks per second, ticks per millisecond etc.
Nguồn:https://wijstaanvooronzegrondrechten.org/
Operating system concepts explained in C#. Gorgeous!!!
You made my day…Saved my life…Great video and teacher
Question is , WHY during concurrent access, sometimes we get less than 3 million? How can a thread make a mistake in the for loop?
i have a question , how do i make solution not close as soon as i open it ? i used to use Console.Readkey(); at the end but even that fails at times, because it keeps telling me that It is not present withing the class/system or w/e it's called. so i'm kind of stuck
y iam getting the same result ,if i use one 10 instead of 1 million?
When I tried using interlocked.increment method instead of ++ operator, the performance is greatly affecting. Can anyone explain this. ??
Even though when I use Interlocked.Increment(), am getting different values. (in VS 2015)
Interesting that the performance gain by allowing all 3 threads to access the method is about 3 times faster than the single-threaded option.
I suppose it makes sense, but programming tends to make me expect seemingly nonsensical answers, despite their perfectly logical foundation.
I really enjoyed this video, too. Thank you very much!
Can anybody explain how we were getting value less than 3000000?!
Great video. One question, it is necesary to use join when we are using lock statement? Than you.
thanks a lot. very helpful
more vids venkat. awesome series. you should make a series for people like me that have little to no experience programming, and know little about how computers work.. alot of being successful programming is knowing how computers work, and these thread videos are a great example of this.
I appreciate your efforts Kudvenkat ,just curious about something do you have a video exclusively on IOC
Sir, On the lock(_lock) , sample, Why is it enough to lock the increments to prevent other threads? I thought the lock should have been on the for loop. I'm thinking that if the current thread goes out of the lock(_lock) and into the for loop, then other threads can sneak into the lock(_lock). Would this be possible?
Thnx a lot Sir…Happy Holi
Happy holi kudvenkat 🙂
Dear Kudvenkat ! I really do not know if u have videos about dependency injection in c# ! I really do not understand this subject and the reason is i could not understand it is no real example that i could feel the importance of this topic ! please reply me !