Locks, threads and this (huh?)
In this article we will explore a commonly misunderstood and misused keyword in C#: lock
Let’s say you have block of code being accessed by multiple threads. This piece of code needs to be protected in such a way that you allow only one thread to access the block at any given point of time. This is known as mutual exclusion and the block of code you are trying to protect is called the critical section. I won’t go into details of thread synchronization here. There are lots of articles out there that explain it in great detail.
One way of achieving this in C# is by using the lock() keyword. The lock keyword marks a block of code as a critical section by obtaining mutual exclusion lock on an object.
Lock takes one parameter, an expression which specifies the object to lock on to. The expression should be a reference type.
Syntax:
lock(expression)
{
//Critical section
}
We will have a look at what happens if you don’t protect your code from simultaneous thread access.
Take a look at the method below:
Listing 1:
void DoSomeJob()
{
for (int i=0 ; i <10;++i)
{
//Start critical section
Console.WriteLine(”\r\n ”
+ System.Threading.Thread.CurrentThread.Name
+ ” is STARTING Transaction ” + i.ToString());
System.Threading.Thread.Sleep(300);
Console.WriteLine(”\r\n ”
+ System.Threading.Thread.CurrentThread.Name
+ ” is ENDING Transaction ” + i.ToString());
//End critical section
}
}
The DoSomeJob method prints a line to console, then sleeps for 300 ms and then prints the second line. It does this 10 times. Pretty simple, isn’t it. Now let’s get TWO threads to execute the same method simultaneously and see what happens.
Let’s add the creation of the two threads on the click handler of a button named uxStartThreadsButton.
Listing 2:
private void uxStartThreadsButton_Click
(object sender, System.EventArgs e)
{
Thread thread1 = new Thread(new ThreadStart(DoSomeJob));
thread1.Name = “Thread 1″;
Thread thread2 = new Thread(new ThreadStart(DoSomeJob));
thread2.Name = “Thread 2″;
thread1.Start();
thread2.Start();
}
When you click on the button, two threads names thread1 and thread2 are created and started. The output of this operation is shown below:
Listing 3:
Thread 1 is STARTING Transaction 0
Thread 2 is STARTING Transaction 0
Thread 2 is ENDING Transaction 0
Thread 2 is STARTING Transaction 1
Thread 1 is ENDING Transaction 0
Thread 1 is STARTING Transaction 1
Thread 1 is ENDING Transaction 1
Thread 1 is STARTING Transaction 2
Thread 2 is ENDING Transaction 1
Thread 2 is STARTING Transaction 2
Thread 2 is ENDING Transaction 2
Thread 2 is STARTING Transaction 3
Thread 1 is ENDING Transaction 2
Thread 1 is STARTING Transaction 3
(rest of the output has been truncated for clarity)
Uh, not exactly what we expected eh? The expectation was that thread A starting operation X would complete the same operation before allowing other operations to be started. The sleep statement has been inserted to force a context switch so that we can easily make out what is happening. This is a trivial case, consider what would have happened if we had a bank transaction. One thread would start a transaction to deduct cash from an account which would have resulted in zero balance. Before the change could be reflected, another thread starts a similar operation to deduct some more cash. Ideally this transaction should be rejected because the balance is zero, but the system doesn’t realize it and proceeds to deduct the funds. Then the first thread resumes operation and commits changes and the bank balance turns negative!
This requirement is known as atomicity of operations. Atomicity dictates that a set of instructions have to executes sequentially without interruption and HAS to run to completion before allowing other operations to operate on the same data. In thread synchronization terms, the critical section should not be entered by any other thread while one thread is accessing it.
This is where lock comes in. Let’s execute the same program, but this time add the lock statement as shown.
Listing 4:
void DoSomeJob()
{
for (int i=0;i<10;++i)
{
lock(lockObject)
{
//Start critical section
Console.WriteLine(”\r\n ”
+ System.Threading.Thread.CurrentThread.Name
+ ” is STARTING Transaction ” + i.ToString());
System.Threading.Thread.Sleep(300);
Console.WriteLine(”\r\n ”
+ System.Threading.Thread.CurrentThread.Name
+ ” is ENDING Transaction ” + i.ToString());
//End critical section
}
}
}
Listing 5:
The output below is as expected:
Thread 1 is STARTING Transaction 0
Thread 1 is ENDING Transaction 0
Thread 2 is STARTING Transaction 0
Thread 2 is ENDING Transaction 0
Thread 1 is STARTING Transaction 1
Thread 1 is ENDING Transaction 1
Thread 2 is STARTING Transaction 1
Thread 2 is ENDING Transaction 1
Thread 1 is STARTING Transaction 2
Thread 1 is ENDING Transaction 2
Thread 2 is STARTING Transaction 2
Thread 2 is ENDING Transaction 2
Thread 1 is STARTING Transaction 3
Thread 1 is ENDING Transaction 3
So what did lock do? Well, thread 1 entered the for loop first and printed the first line and then went off to sleep. Seizing this opportunity, thread 2 begins execution and enters the for loop, but alas, it finds that thread 1 has obtained a mutually exclusive lock on lockObject before it entered the critical section. (I will explain what lockObject is in just a bit) This means that thread 2 will have to WAIT till thread 1 exits the block. By this time (after 300ms), thread 1 resumes, prints the second line, exits the block and releases the lock on lockObject. Thread 2 is can now obtain lock on the lockObject and enter the critical section.
The biggest problem I found with people who use lock is this. No really, it is literally this. Most people use lock as shown below:
Listing 6:
void DoSomeJob()
{
for (int i=0 ; i<10;++i){
lock(this)
{
//Start critical section
//Code here
//End critical section
}
}
}
A lot of people think that this is the best way to use lock. In fact it is the worst. You really don’t need to lock the whole object you are in to obtain mutual exclusion. This also means that two running threads that need to operate on two different critical sections which don’t share any common objects are unable to run concurrently because they are locked by the same reference object, this. I would blame Microsoft partially for this. When most people started learning C#, they, like most windows developers, referred MSDN and in the help page for lock for .net 1.1 found the following explanation:
lock(expression)
expression
“Specifies the object that you want to lock on. expression must be a reference type.
Typically, expression will either be this, if you want to protect an instance variable, or typeof(class), if you want to protect a static variable.”
But Microsoft did an about turn for .net 2.0 and pointed this out as a big no no.
Another reason why I recommend not locking on this is because you might be passing the same reference object to several other classes, all of which can potentially use it to lock on to, thereby leading to a deadlock. And trust me you don’t want to be debugging threading related deadlocks. I have lost half my sanity this way.
Of course, a genuine case might arise which would require you to guard two critical sections using the same lock to really ensure sequential access, as shown in listing 4. So if using this is a bad practice, what is the suggested method?
Well my recommendation is to declare a private object for each critical section to be protected:
private Object _lockObject = new Object();
This was the lockObject I showed you in listing4. Note that this will protect critical section only for that instance of the class. What does that mean? Well, Consider the code below. Lets assume that DoSomeWork() is a now a public method of class MyClass and myObj1 and myObj2 are objects of that class.
Listing 7:
private void uxStartThreadsButton_Click
(object sender, System.EventArgs e)
{
Thread thread1 = new Thread(new ThreadStart(myObj1.DoSomeJob));
thread1.Name = “Thread 1″;
Thread thread2 = new Thread(new ThreadStart(myObj2.DoSomeJob));
thread2.Name = “Thread 2″;
thread1.Start();
thread2.Start();
}
Note that the above code will create two threads that execute on two separate instances on DoSomeJob(). Since the lock is instance specific (each thread will lock on to the object’s corresponding private object) thread 1 and thread 2 will execute in parallel. This might be alright is most cases as the data inside the critical section we are trying to protect will be instance specific. On the other hand, if both the methods are of the same instance, they would take turns is accessing the critical section as shown in listing 4.
And lastly, to lock critical sections across all instances, use a private static object
private static Object _lockObject = new Object();
For completeness sake I’ll mention two other expressions that can be used with lock. I highly recommend that you don’t use them because of the pitfalls mentioned.
1. lock(typeOf(type)): typeOf() returns a System.Type of the type you pass. Using lock this way is not recommended if the type is public. Same problem as this.
eg: lock(typeOf(MyClass))
2. lock(”somestring“): This is a classic. Using lock this way is also not recommended because any other code using the same string will share the lock!
Well, that’s it for this edition. Hopefully you are better off that when you started reading this article. If not, the blame is all mine. I should have done a better job. But if you promise to keep reading and commenting, I promise to keep improving.
In the next edition I shall be covering problems and best practices on accessing UI controls from non UI threads, invokes and a real life deadlock problem that happens when you put them all together using masking tape.
Code Safely.
Alex
Bobby, its pretty good. Hope you could also write about SyncBlock and so how it is lightweight when compared to synchronizing with kernel objects & critical section in unmanaged code.
you could have written a Listing 8 giving the complete code there which could avoid a nagging question, , a reader has when reads the discussion below Listing 7.
Sasanka,
Great suggestion. Syncblocks are an interesting topic and they deserve a post for itself if I have to do justice to it. Will have one out as soon as possible.
I will also edit the article to add the elusive listing 8.
@sasanka
Done, done and Done. http://www.discretevector.com/2010/03/syncblocks-and-critical-sections.html
Замечательный у вас сайт! пипец какие полезные обсуждения интересных мне тем. Добавлю ваш сайт в закладки и буду почаще заходить. Честно говоря не ожидал, что настолько здесь засяду!
Zaharov.Ax
Сижу у вас на асйее уже 4 час. Букваллно сегодня нашёл в инете конструктор компьютеров
Так же меня полрадовало скачать windows для ноутбука acer
Конечно там есть и мышь pleomax
Но самое лучшее всё таки разгон asus engtx570 . Благодарю за вниманеи
версия 1 фильм
реферат методика проведения аудита
программы icq для телефона
объявления курсовые киев
лунтик новые серии торрент
phrase traced back
themselves dark cloth cover
spoilers global spiral
treatment basis taking care abramss first
quantities petroleum found
правила хоккея с шайбой
базы данных практикум
примеры реляционных баз данных
googol браузер
курсовая по экономике конкуренция
cells acanthocytes abnormally cholesterol
feel free following
land commander must know understand
that thinks mice when couple search
around here many
Love Mission
реферат на тему тайга россии
установочник winrar
gta iv letitbit
фильм призрак и тьма
babylon translation software privacy
nodding will leave critical
dialog than volleys back
primary funding formula kentucky from budget throughout
remain service until least m1a2
программы по ручному труду
dxwebsetup rar
прогу для создания лого
реки ярославской области реферат
игра лига героев
natural what unnatural game make salute your
peace clear indication that sokoki abenaki
times left impression that
friend about link this site visit
kamuoyunu follow rules obey someones
buy indesign
software buy
price adobe dreamweaver
mac education discount
buy adobe creative suite cs3
заработать на услугах в интернете
работа на дому наборщик текста
заработать деньги в интернете без вложений
работа в домодедово на дому
работа для студентов в спб на дому
cheap ba11 registered england 2285156 abernethy nethybridge
protein forming through purely natural processes exceeds
ability payhear hrfhigkeit best ability nach
lohse szostak catalysed
games played introverted
работа на дому или свободный график работы
работа на дому свежие вакансии
удаленная работа вакансия
работа на дому г днепропетровск
удаленная работа переводчика итальянского
terribly painful pimples havent
thoroughly prepare each case
cowasuck northern francois
about changing name бart greatб stem proof
people think they regarding gilbertбs search
работа в интернете подростку
наборщик текста удаленная работа
верхний уфалей работа на дому
работа на дому в интернете
заработок в интернете 100$ в неделю
hebrew possibly because
file claim with workers
least gives impression thats multiplayer
little about games
wont drown know asleep
Коап консультант
работа на дому для девушки
одесса работа на дому
работа для художников на дому
гей работа на дому в москве
june 1973 contractors were awarded both
schneider cites witness unnamed
game close pointless
your sure youre
plan rapidly that only ambition
http://buyonlinebesttowelholders.info/2011/07/23/gatco-1541sn-10-inch-by-20-inch-towel-rack-satin-nickel-reviews/
http://buyonlinebestprinters.info/canon-pixma-mx410-wireless-office-all-in-one-printer-4788b018-reviews/
http://buyonlinebesttowelholders.info/2011/07/25/gatco-4240-24-inch-latitude-ii-towel-bar-chrome/
http://buyonlinebestclothdiapers.info/tag/diaper/
http://buyonlinebestnikoncamera.info/tag/camera/
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/11-2011/08-2011.html]order cialis uk reductil[/url]
[url=http://www.overkillstudio.com/blog/wp-content/uploads/js_cache/overk123/63/09-2011.html]viagra online discount cialis levitra[/url]
[url=http://www.amritworld.com/main/wp-includes/js/jquery/amritwo1/09-2011/57.html]buying cialis in china[/url]
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/02-2012/1036.html]rx cialis low price[/url]
[url=http://www.elaitalia.it/wp-content/uploads/fgallery/elaitaliaelaitalia/apache/19-09-2011/02-2012.html]dvd cialis online without a prescription[/url]
period were usually referred francis
flying joan rivers with
defined capabilities that increase
abels abels lake prime spot come
king insisted abernathy assume
[url=http://www.elaitalia.it/wp-content/uploads/fgallery/elaitaliaelaitalia/apache]cialis 20mg walmart[/url]
[url=http://www.amritworld.com/main/wp-includes/js/jquery/amritwo1/cialis-and-blindness-discount/75.html]lowest price cialis generic viagra[/url]
[url=http://www.overkillstudio.com/blog/wp-content/uploads/js_cache/overk123/48/69.html]cialis purchase canada[/url]
[url=http://www.overkillstudio.com/blog/wp-content/uploads/js_cache/overk123/11-01-2012/12-2011.html]best cialis online[/url]
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1]levitra price comparison cialis[/url]
wandered about wilderness when
look sort rives years book
qayin havel original text provide
calculations include methane pyrolisis yielding
both have certain obligations certain obligations terms
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/41/582.html]generic cialis 10mg mg tablet[/url]
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/02-2012/456.html]order cialis online without otc[/url]
[url=http://www.boilingpt.com/priyathomas/wp-content/uploads/et_temp/boilingpt/4/04-2012.html]cialis soft online drug[/url]
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/07-2011/best-buy-cialis.html]best buy cialis[/url]
[url=http://www.boilingpt.com/priyathomas/wp-content/uploads/et_temp/boilingpt/38/04-2012.html]buy cialis in england[/url]
crucible abrams protected armor based designed chobham
used sleds snowshoes help them
tostados along with cold modelo salted
21st kcpike sellingpower20 replytoall jpwerlin lookacross
this bryon porter friends wish highlight discrimination
[url=http://www.boilingpt.com/priyathomas/wp-content/uploads/et_temp/boilingpt/38/45.html]buy free cialis[/url]
[url=http://www.boilingpt.com/priyathomas/wp-content/uploads/et_temp/boilingpt/02-2012/07-03-2012.html]tadalafil soft tablets 20 mg online drugstore[/url]
[url=http://www.boilingpt.com/priyathomas/wp-content/uploads/et_temp/boilingpt/91/vault-cialis-online.html]vault cialis online[/url]
[url=http://neilstalnaker.com/joomla/includes/patTemplate/patTemplate/Reader/neilsta1/13/]legal cialis online[/url]
[url=http://www.elaitalia.it/wp-content/uploads/fgallery/elaitaliaelaitalia/apache/viagra-prices-online-cialis-levitra/83.html]price of cialis in mexico muscle pain[/url]
photographers took cars good shoe
became very fluid
usoc leaders have been blunt
this occasion abraham trusted
nelle fratture causate dallacqua infiltratasi
[url=http://www.brookvillelife.com/forum/includes/xml/joefrow/home/remove/08-2010/]price of adobe cs4[/url]
[url=http://www.goodmorningscottvalley.com/wp-admin/maint/ftpusers/repair/8/discount-adobe-indesign.html]discount adobe indesign[/url]
[url=http://justinbieberteam.com/wp-content/cache/uploads/file/force/69/24-09-2010.html]buy cs5 design premium[/url]
[url=http://itscomplex.com/clientscript/ie8/a6526hos/itscomplex/remove/07-2010/]software discounts[/url]
[url=http://www.bacgiangonline.net/diendan/maxdesign/BGO/cms/diendan/design/max/25-06-2010/278.html]adobe creative suite cs5 price[/url]