You are on page 1of 22

SynchronlzaLlon

unl1 v
Jhy SynchronlzaLlon?
W Assume your Lwo Lhreads are accesslng a
daLabase record raLher Lhan readlng a
member varlable
W lor example your code mlghL be parL of an
lnvenLory sysLem for a book reLaller
W A cusLomer asks lf ltoqtommloq c# ls
avallable
W 1he flrsL Lhread reads Lhe value and flnds LhaL
Lhere ls one book on hand 1he cusLomer
wanLs Lo buy Lhe book so Lhe Lhread proceeds
Lo gaLher credlL card lnformaLlon and valldaLe
Lhe cusLomers address
Jhy SynchronlzaLlon?
W Jhlle Lhls ls happenlng a second Lhread asks lf
Lhls wonderful book ls sLlll avallable
W 1he flrsL Lhread has noL yeL updaLed Lhe record
so one book sLlll shows as avallable
W 1he second Lhread beglns Lhe purchase process
W Meanwhlle Lhe flrsL Lhread flnlshes and
decremenLs Lhe counLer Lo zero
W 1he second Lhread bllssfully unaware of Lhe
acLlvlLy of Lhe flrsL also seLs Lhe value back Lo
zero
W unforLunaLely you have now sold Lhe same copy
of Lhe book Lwlce
SynchronlzaLlon
W SynchronlzaLlon ls provlded by a lock on Lhe
ob[ecL whlch prevenLs a second Lhread from
barglng ln on your ob[ecL unLll Lhe flrsL Lhread
ls flnlshed wlLh lL
W Lhree synchronlzaLlon mechanlsms provlded
by Lhe CL8
Lhe lnLerlock class
Lhe C# lock sLaLemenL and
Lhe MonlLor class
Us|ng Inter|ocked
W C# offers a speclal class lnLerlocked [usL for
Lhls purpose
W lnLerlocked has Lwo meLhods
lncremenL and
uecremenL
W whlch noL only lncremenL or decremenL a
value buL also do so under synchronlzaLlon
conLrol
Modlfy Lhe lncremenLer meLhod
W public void Incrementer( )
W
W try
W
W while (counter 1000)
W
W Interlocked.Increment(ref counter);
W simulate some work in this method
W Thread.Sleep(1);
W assign the decremented value and display the results
W Console.WriteLine(
W "Thread 0}. Incrementer: 1}", Thread.CurrentThread.Name,
counter);
W }
W }
W }
Us|ng Locks
W AlLhough Lhe lnLerlocked ob[ecL ls flne lf you
wanL Lo lncremenL or decremenL a value
Lhere wlll be Llmes when you wanL Lo conLrol
access Lo oLher ob[ecLs as well
W 1hls ls provlded by Lhe nL1 Lock ob[ecL
W A lock marks a crlLlcal secLlon of your code
provldlng synchronlzaLlon Lo an ob[ecL you
deslgnaLe whlle Lhe lock ls ln effecL
Lock(expresslon)
W 1he synLax of uslng a Lock ls Lo requesL a lock
on an ob[ecL and Lhen Lo execuLe a sLaLemenL
or block of sLaLemenLs 1he lock ls removed aL
Lhe end of Lhe sLaLemenL block
W C# provldes dlrecL supporL for locks Lhrough
Lhe lock keyword ass ln a reference ob[ecL
and follow Lhe keyword wlLh a sLaLemenL
block
W lock(exptessloo) stotemeotblock
W public void Incrementer( )
W
W try
W
W while (counter 1000)
W
W lock (this)
W
W int temp counter; temp ; Thread.Sleep(1); counter temp;
W }
W assign the decremented value and display the results
W Console.WriteLine(
W "Thread 0}. Incrementer: 1}", Thread.CurrentThread.Name, counter);
W }
W }
Us|ng Mon|tors
W lor Lhe mosL sophlsLlcaLed conLrol over
resources you mlghL wanL Lo use a mooltot
W A monlLor leLs you declde when Lo enLer and exlL
Lhe synchronlzaLlon and lL leLs you walL for
anoLher area of your code Lo become free
W A monlLor acLs as a smarL lock on a resource
W Jhen you wanL Lo begln synchronlzaLlon call Lhe
LnLer( ) meLhod of Lhe monlLor passlng ln Lhe
ob[ecL you wanL Lo lock
W MonlLorLnLer(Lhls)
JalL( )
W lf Lhe monlLor ls unavallable Lhe ob[ecL
proLecLed by Lhe monlLor ls ln use
W ?ou can do oLher work whlle you walL for Lhe
monlLor Lo become avallable and Lhen Lry
agaln
W ?ou can also expllclLly choose Lo JalL( )
suspendlng your Lhread unLll Lhe momenL Lhe
monlLor ls free
W JalL( ) helps you conLrol Lhread orderlng
Lxample
W lor example suppose you are downloadlng
and prlnLlng an arLlcle from Lhe Jeb
W lor efflclency youd llke Lo prlnL ln a background
Lhread buL you wanL Lo ensure LhaL aL leasL 10
pages have downloaded before you begln
W ?our prlnLlng Lhread wlll walL unLll Lhe geLflle
Lhread slgnals LhaL enough of Lhe flle has been
read
W ?ou donL wanL Lo !oln Lhe geLflle Lhread because
Lhe flle mlghL be hundreds of pages
W ?ou donL wanL Lo walL unLll lL has compleLely
flnlshed downloadlng buL you do wanL Lo ensure
LhaL aL leasL 10 pages have been read before your
prlnL Lhread beglns
W 1he JalL( ) meLhod ls [usL Lhe LlckeL
MonlLorJalL(Lhls)
W 1o slmulaLe Lhls rewrlLe 1esLer and add back Lhe
decremenLer meLhod ?our lncremenLer wlll counL up Lo 3
1he decremenLer meLhod wlll counL down Lo zero lL Lurns
ouL you donL wanL Lo sLarL decremenLlng unless Lhe value
of counLer ls aL leasL 3
W ln decremenLer call LnLer on Lhe monlLor 1hen check Lhe
value of counLer and lf lL ls less Lhan 3 call JalL on Lhe
monlLor
W lf (counLer 3)
W
W MonlLorJalL(Lhls)
W
W 1hls call Lo JalL( ) frees Lhe monlLor buL slgnals Lhe CL8
LhaL you wanL Lhe monlLor back Lhe nexL Llme lL ls free
MonlLorulse(Lhls)
W JalLlng Lhreads wlll be noLlfled of a chance Lo
run agaln lf Lhe acLlve Lhread calls ulse( )
W MonlLorulse(Lhls)
W ulse( ) slgnals Lhe CL8 LhaL Lhere has been a
change ln sLaLe LhaL mlghL free a Lhread LhaL ls
walLlng
W 1he CL8 wlll keep Lrack of Lhe facL LhaL Lhe earller
Lhread asked Lo walL and Lhreads wlll be
guaranLeed access ln Lhe order ln whlch Lhe
walLs were requesLed (?our walL ls lmporLanL Lo
us and wlll be handled ln Lhe order recelved)
W Jhen a Lhread ls flnlshed wlLh Lhe monlLor lL can
mark Lhe end of lLs conLrolled area of code wlLh a
call Lo LxlL( )
W vold uecremenLer( )
W
W Lry
W // synchronlze Lhls area of code
W MonlLorLnLer(Lhls)
W // lf counLer ls noL yeL 10 Lhen free Lhe monlLor Lo oLher walLlng Lhreads buL walL ln llne for your Lurn
W lf (counLer 10)
W
W ConsoleJrlLeLlne( 0 ln uecremenLer CounLer 1 CoLLa JalL! 1hreadCurrenL1hreadname
counLer)
W MonlLorJalL(Lhls)
W
W whlle (counLer 0)
W
W long Lemp counLer Lemp 1hreadSleep(1)
W counLer Lemp
W ConsoleJrlLeLlne( 0 ln uecremenLer CounLer 1 1hreadCurrenL1hreadname counLer)
W
W
W flnally
W
W MonlLorLxlL(Lhls)
W
W vold lncremenLer( )
W
W Lry
W
W MonlLorLnLer(Lhls)
W whlle (counLer 10)
W
W long Lemp counLer Lemp++ 1hreadSleep(1)
W counLer Lemp ConsoleJrlLeLlne( 0 ln lncremenLer CounLer 1
W 1hreadCurrenL1hreadname counLer)
W
W // lm done lncremenLlng for now leL anoLher Lhread have Lhe MonlLor
W MonlLorulse(Lhls)
W
W flnally
W
W ConsoleJrlLeLlne(0 LxlLlng 1hreadCurrenL1hreadname)
W MonlLorLxlL(Lhls)
W
W
W ln Lhls example decremenLer ls sLarLed flrsL
W ln Lhe ouLpuL you see 1hread1 (Lhe
decremenLer) sLarL up and Lhen reallze LhaL lL has
Lo walL
W ?ou Lhen see 1hread2 sLarL up
W Cnly when 1hread2 pulses does 1hread1 begln lLs
work
W 1ry some experlmenLs wlLh Lhls code
W llrsL commenL ouL Lhe call Lo ulse( )
W ?oull flnd LhaL 1hread1 never resumes
W JlLhouL ulse( ) Lhere ls no slgnal Lo Lhe walLlng
Lhreads
fce Cond|t|ons fnd Defd|ocks
W 1hread synchronlzaLlon can be Lrlcky
especlally ln complex programs
W lf you do declde Lo creaLe your own Lhreads
you musL confronL and solve all Lhe LradlLlonal
problems of Lhread synchronlzaLlon such as
race condlLlons and deadlock
fce Cond|t|ons
W A toce cooJltloo exlsLs when Lhe success of your
program depends on Lhe unconLrolled order of
compleLlon of Lwo lndependenL Lhreads
W Suppose for example LhaL you have Lwo Lhreads one
ls responslble for openlng a flle and Lhe oLher ls
responslble for wrlLlng Lo Lhe flle l
W L ls lmporLanL LhaL you conLrol Lhe second Lhread so
LhaL lLs assured LhaL Lhe flrsL Lhread has opened
Lhe flle
W under oLher unpredlcLable condlLlons Lhe flrsL Lhread
wonL flnlsh openlng Lhe flle before Lhe second Lhread
Lrles Lo wrlLe Lo lL and youll Lhrow an excepLlon (or
worse your program wlll slmply selze up and dle)
W 1hls ls a race condlLlon and race condlLlons can be very
dlfflculL Lo debug
W ?ou cannoL leave Lhese Lwo Lhreads Lo operaLe
lndependenLly
W you musL ensure LhaL 1hread1 wlll have
compleLed before 1hread2 beglns
W 1o accompllsh Lhls you mlghL !oln( ) 1hread2
on 1hread1
W As an alLernaLlve you can use a MonlLor and
JalL( ) for Lhe approprlaLe condlLlons before
resumlng 1hread2
Defd|ock
W Jhen you walL for a resource Lo become free you are
aL rlsk of JeoJlock also called a JeoJly embtoce
W ln a deadlock Lwo or more Lhreads are walLlng for
each oLher and nelLher can become free
W Suppose you have Lwo Lhreads 1hreadA and 1hread8
W 1hreadA locks down an Lmployee ob[ecL and Lhen Lrles
Lo geL a lock on a row ln Lhe daLabase lL Lurns ouL LhaL
1hread8 already has LhaL row locked so 1hreadA walLs
W unforLunaLely 1hread8 canL updaLe Lhe row unLll lL
locks down Lhe Lmployee ob[ecL whlch ls already
locked down by 1hreadA
W nelLher Lhread can proceed and nelLher Lhread wlll
unlock lLs own resource 1hey are walLlng for each
oLher ln a deadly embrace
SoluLlon
W ln a program runnlng many Lhreads deadlock can
be very dlfflculL Lo dlagnose leL alone solve
W Cne guldellne ls Lo geL all Lhe locks you need or
Lo release all Lhe locks you have
W 1haL ls as soon as 1hreadA reallzes LhaL lL canL
lock Lhe 8ow lL should release lLs lock on Lhe
Lmployee ob[ecL
W Slmllarly when 1hread8 canL lock Lhe Lmployee
lL should release Lhe 8ow
W A second lmporLanL guldellne ls Lo lock as small a
secLlon of code as posslble and Lo hold Lhe lock as
brlefly as posslble

You might also like