VB2008´ÓÈëÃŵ½¾«Í¨(PDF¸ñʽӢÎÄ°æ)-µÚ100²¿·Ö
°´¼üÅÌÉÏ·½Ïò¼ü ¡û »ò ¡ú ¿É¿ìËÙÉÏÏ·ҳ£¬°´¼üÅÌÉ쵀 Enter ¼ü¿É»Øµ½±¾ÊéĿ¼ҳ£¬°´¼üÅÌÉÏ·½Ïò¼ü ¡ü ¿É»Øµ½±¾Ò³¶¥²¿£¡
¡ª¡ª¡ª¡ªÎ´ÔĶÁÍꣿ¼ÓÈëÊéÇ©ÒѱãÏ´μÌÐøÔĶÁ£¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡You¡¡need¡¡to¡¡instantiate¡¡a¡¡single¡¡ThreadedTask¡¡and¡¡associate¡¡it¡¡with¡¡a¡¡single¡¡Thread¡¡instance£»¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡like¡¡this£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡task1¡¡As¡¡ThreadedTask¡¡=¡¡New¡¡ThreadedTask£¨¡¨hello¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡task2¡¡As¡¡ThreadedTask¡¡=¡¡New¡¡ThreadedTask£¨¡¨goodbye¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡Thread¡¡=¡¡New¡¡Thread£¨AddressOf¡¡task1¡£MethodToRun£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡Thread¡¡=¡¡New¡¡Thread£¨AddressOf¡¡task2¡£MethodToRun£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡If¡¡you¡¡are¡¡running¡¡a¡¡stateful¡¡method£»¡¡you¡¡need¡¡to¡¡associate¡¡a¡¡task¡¡instance¡¡with¡¡a¡¡thread¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡instance¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Using¡¡a¡¡Thread¡¡Parameter¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Suppose¡¡that¡¡you¡¡want¡¡to¡¡create¡¡a¡¡stateful¡¡thread¡£¡¡You¡¡can¡¡do¡¡this¡¡by¡¡using¡¡a¡¡thread¡¡parameter¡£¡¡In¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡other¡¡words£»¡¡the¡¡method¡¡that¡¡you¡¡invoke¡¡on¡¡another¡¡thread¡¡takes¡¡a¡¡parameter¡£¡¡Here¡¯s¡¡an¡¡example£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡371¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡C¡¡HA¡¡P¡¡TE¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡AR¡¡N¡¡IN¡¡G¡¡¡¡¡¡AB¡¡O¡¡U¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡IT¡¡HR¡¡E¡¡AD¡¡IN¡¡G¡¡349¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡SimpleThreadWithStateTask£¨ByVal¡¡buffer¡¡As¡¡Object£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨You¡¡said¡¡£¨¡¨¡¡&¡¡buffer¡£ToString£¨£©¡¡&¡¡¡¨£©¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Private¡¡Sub¡¡SimpleThreadWithState£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡SimpleThreadWithStateTask£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨¡¨my¡¡text¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡major¡¡difference¡¡with¡¡a¡¡thread¡¡parameter¡¡is¡¡that¡¡you¡¡declare¡¡the¡¡function¡¡that¡¡is¡¡executed¡¡¡¡
with¡¡a¡¡parameter£»¡¡and¡¡the¡¡¡¡Start£¨£©¡¡method¡¡has¡¡a¡¡parameter¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Two¡¡restrictions¡¡apply¡¡to¡¡using¡¡a¡¡thread¡¡parameter£º¡¡you¡¡can¡¡send¡¡only¡¡a¡¡single¡¡parameter£»¡¡¡¡
and¡¡that¡¡parameter¡¡must¡¡be¡¡an¡¡object¡£¡¡
Synchronizing¡¡Between¡¡Threads¡¡
When¡¡you¡¡have¡¡two¡¡threads¡¡and¡¡both¡¡share¡¡state¡¡£¨such¡¡as¡¡a¡¡variable£©£»¡¡a¡¡concurrency¡¡situation¡¡¡¡
may¡¡arise¡£¡¡Sharing¡¡state¡¡between¡¡two¡¡independent¡¡threads¡¡is¡¡not¡¡a¡¡problem¡¡if¡¡both¡¡threads¡¡¡¡
consider¡¡the¡¡data¡¡as¡¡read¡only¡£¡¡What¡¡does¡¡the¡¡reading¡¡thread¡¡read£¿¡¡Is¡¡the¡¡state¡¡consistent£¿¡¡It¡¡is¡¡¡¡
probably¡¡not¡¡consistent£»¡¡and¡¡that¡¡is¡¡why¡¡you¡¡need¡¡to¡¡synchronize¡¡access¡¡to¡¡state¡£¡¡
¡¡¡¡¡¡¡¡¡¡Let¡¯s¡¡consider¡¡a¡¡simple¡¡¡¡collection¡¡class¡¡example¡£¡¡The¡¡following¡¡source¡¡code¡¡executes¡¡¡¡
in¡¡the¡¡calling¡¡thread£»¡¡instantiates¡¡a¡¡list¡¡collection£»¡¡and¡¡then¡¡adds¡¡two¡¡numbers¡¡to¡¡the¡¡collection¡£¡¡
Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡
elements¡£Add£¨10£©¡¡
elements¡£Add£¨20£©¡¡
¡¡¡¡¡¡¡¡¡¡In¡¡the¡¡next¡¡step£»¡¡we¡¡define¡¡a¡¡method¡¡that¡¡iterates¡¡the¡¡elements¡¡collection¡¡£¨which¡¡is¡¡declared¡¡at¡¡¡¡
a¡¡higher¡¡scope£©¡£¡¡
Sub¡¡Task1£¨£©¡¡
¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡
¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡elements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡Next¡¡
End¡¡Sub¡¡¡¡
¡¡¡¡¡¡¡¡¡¡This¡¡thread¡¡iterates¡¡the¡¡data£»¡¡and¡¡the¡¡two¡¡Thread¡£Sleep£¨£©¡¡calls¡¡put¡¡the¡¡threads¡¡to¡¡sleep¡¡for¡¡¡¡
1000¡¡milliseconds£»¡¡or¡¡1¡¡second¡£¡¡By¡¡putting¡¡the¡¡thread¡¡to¡¡sleep£»¡¡we¡¡can¡¡artificially¡¡construct¡¡a¡¡¡¡
situation¡¡where¡¡another¡¡thread¡¡adds¡¡to¡¡the¡¡collection¡¡while¡¡the¡¡collection¡¡is¡¡being¡¡iterated¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡method¡¡that¡¡adds¡¡an¡¡element¡¡to¡¡the¡¡collection¡¡is¡¡defined¡¡as¡¡follows£º¡¡
Sub¡¡Task2£¨£©¡¡
¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡
¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡
End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡372¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
350¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡A¡¡B¡¡OU¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡I¡¡TH¡¡R¡¡E¡¡A¡¡DI¡¡N¡¡G¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡Task1£¨£©¡¡and¡¡Task2£¨£©¡¡methods¡¡are¡¡started¡¡in¡¡separate¡¡threads¡¡as¡¡follows£º£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Running¡¡the¡¡threaded¡¡code¡¡will¡¡generate¡¡an¡¡exception£»¡¡but¡¡not¡¡immediately¡£¡¡First£»¡¡the¡¡caller¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread¡¡creates¡¡and¡¡starts¡¡thread1¡¡and¡¡thread2¡£¡¡thread1¡¡goes¡¡to¡¡sleep¡¡for¡¡1¡¡second£»¡¡and¡¡thread2¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡goes¡¡to¡¡sleep¡¡for¡¡1¡£5¡¡seconds¡£¡¡After¡¡thread1¡¡awakens£»¡¡one¡¡item¡¡in¡¡the¡¡collection¡¡is¡¡iterated£»¡¡and¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡¡goes¡¡to¡¡sleep¡¡for¡¡another¡¡second¡£¡¡But¡¡before¡¡thread1¡¡reawakens£»¡¡thread2¡¡awakens¡¡and¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡adds¡¡an¡¡element¡¡to¡¡the¡¡collection¡£¡¡When¡¡thread1¡¡reawakens¡¡and¡¡attempts¡¡to¡¡iterate¡¡another¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡element¡¡in¡¡the¡¡collection£»¡¡an¡¡exception¡¡is¡¡generated£»¡¡as¡¡shown¡¡in¡¡Figure¡¡13¡4¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Figure¡¡13¡4¡£¡¡Exception¡¡thrown¡¡after¡¡adding¡¡element¡¡to¡¡the¡¡collection£»¡¡as¡¡shown¡¡in¡¡the¡¡Visual¡¡Basic¡¡IDE¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡InvalidOperationException¡¡is¡¡thrown¡¡to¡¡indicate¡¡that¡¡you¡¡can¡¯t¡¡add¡¡elements¡¡to¡¡a¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡collection¡¡while¡¡iterating¡¡a¡¡collection¡£¡¡The¡¡collection¡¡classes¡¡think¡¡it¡¡is¡¡a¡¡bad¡¡idea¡¡to¡¡modify¡¡and¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡iterate¡¡a¡¡collection¡¡at¡¡the¡¡same¡¡time¡£¡¡I¡¡agree¡¡with¡¡the¡¡collection¡¡classes£»¡¡because¡¡doing¡¡so¡¡could¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡give¡¡unpredictable¡¡results¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡problem¡¡in¡¡the¡¡source¡¡code¡¡is¡¡how¡¡to¡¡use¡¡the¡¡collection¡¡classes¡¡in¡¡a¡¡multithreaded¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡context¡£¡¡In¡¡the¡¡example£»¡¡items¡¡are¡¡added¡¡to¡¡the¡¡collection¡¡while¡¡the¡¡collection¡¡is¡¡being¡¡iterated¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡A¡¡monly¡¡suggested¡¡approach¡¡is¡¡to¡¡use¡¡the¡¡type¡¡¡¡System¡£Collections¡£ObjectModel¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ReadOnlyCollection£»¡¡as¡¡in¡¡the¡¡following¡¡example¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Imports¡¡System¡£Collections¡£ObjectModel¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Imports¡¡System¡£Threading¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡373¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡C¡¡HA¡¡P¡¡TE¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡AR¡¡N¡¡IN¡¡G¡¡¡¡¡¡AB¡¡O¡¡U¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡IT¡¡HR¡¡E¡¡AD¡¡IN¡¡G¡¡351¡¡
Module¡¡ThreadProblem¡¡
¡¡¡¡¡¡¡¡Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©¡¡=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡
¡¡¡¡¡¡¡¡Sub¡¡Task1£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡listElements¡¡As¡¡New¡¡ReadOnlyCollection£¨Of¡¡Integer£©£¨elements£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡listElements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Next¡¡
¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡Sub¡¡Task2£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡
¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡Sub¡¡Main£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡End¡¡Sub¡¡
End¡¡Module¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡change¡¡is¡¡the¡¡bolded¡¡code£»¡¡which¡¡instantiates¡¡the¡¡type¡¡System¡£Collections¡£¡¡
ReadOnlyCollection£»¡¡to¡¡which¡¡we¡¡pass¡¡the¡¡elements¡¡list¡£¡¡The¡¡ReadOnlyCollection¡¡provides¡¡the¡¡¡¡
base¡¡class¡¡for¡¡a¡¡generic¡¡read¡only¡¡collection¡£¡¡The¡¡For¡¡Each¡¡iterator¡¡then¡¡iterates¡¡a¡¡collection¡¡¡¡
that¡¡is¡¡read¡only£»¡¡but¡¡based¡¡on¡¡the¡¡original¡¡collection¡£¡¡However£»¡¡running¡¡the¡¡code¡¡will¡¡result¡¡in¡¡¡¡
the¡¡same¡¡exception¡£¡¡This¡¡demonstrates¡¡that¡¡ReadOnlyCollection¡¡does¡¡not¡¡take¡¡a¡¡snapshot£»¡¡but¡¡¡¡
masks¡¡the¡¡collection¡£¡¡The¡¡mask¡¡disables¡¡the¡¡addition¡¡of¡¡items¡¡to¡¡the¡¡collection£»¡¡but¡¡because¡¡the¡¡¡¡
other¡¡thread¡¡is¡¡taking¡¡a¡¡shortcut¡¡and¡¡editing¡¡the¡¡original¡¡collection£»¡¡the¡¡read¡only¡¡collection¡¡is¡¡¡¡
modified¡¡as¡¡well¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Let¡¯s¡¡say¡¡that¡¡converting¡¡the¡¡collection¡¡into¡¡a¡¡read¡only¡¡collection¡¡had¡¡worked¡£¡¡It¡¡would¡¡¡¡
not¡¡have¡¡solved¡¡anything¡£¡¡A¡¡read¡only¡¡collection¡¡means¡¡that¡¡the¡¡second¡¡thread¡¡would¡¡generate¡¡¡¡
an¡¡exception¡¡because¡¡you¡¡can¡¯t¡¡add¡¡elements¡¡to¡¡a¡¡collection¡¡that¡¡is¡¡read¡only¡£¡¡The¡¡point¡¡is¡¡that¡¡¡¡
when¡¡writing¡¡multithreaded¡¡code¡¡that¡¡shares¡¡variables£»¡¡you¡¡don¡¯t¡¡have¡¡an¡¡easy¡¡solution£»¡¡because¡¡¡¡
you¡¡are¡¡trying¡¡to¡¡solve¡¡the¡¡problem¡¡of¡¡how¡¡to¡¡keep¡¡multiple¡¡cooks¡¡productive¡¡in¡¡a¡¡single¡¡kitchen¡£¡¡
¡¡¡¡¡¡¡¡¡¡We¡¡are¡¡trying¡¡to¡¡solve¡¡a¡¡classic¡¡reader/writer¡¡problem£»¡¡where¡¡some¡¡threads¡¡are¡¡interested¡¡¡¡
only¡¡in¡¡reading¡¡the¡¡data£»¡¡and¡¡other¡¡threads¡¡are¡¡interested¡¡only¡¡in¡¡modifying¡¡the¡¡data¡£¡¡One¡¡way¡¡¡¡
to¡¡synchronize¡¡the¡¡readers¡¡and¡¡writers¡¡is¡¡to¡¡use¡¡an¡¡exclusive¡¡lock£»¡¡so¡¡that¡¡only¡¡one¡¡thread¡¡may¡¡¡¡
read¡¡or¡¡write¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡374¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
352¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡A¡¡B¡¡OU¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡I¡¡TH¡¡R¡¡E¡¡A¡¡DI¡¡N¡¡G¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Using¡¡Exclusive¡¡Locks¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡When¡¡using¡¡exclusive¡¡locks¡¡in¡¡£»¡¡you¡¡are¡¡saying£»¡¡¡°Only¡¡one¡¡thread¡¡may¡¡execute¡¡this¡¡piece¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡of¡¡code¡£¡±¡¡If¡¡two¡¡threads¡¡want¡¡to¡¡execute¡¡a¡¡particular¡¡piece¡¡of¡¡code£»¡¡one¡¡will¡¡be¡¡granted¡¡access£»¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡while¡¡the¡¡other¡¡thread¡¡waits¡¡until¡¡the¡¡granted¡¡thread¡¡has¡¡exited¡¡the¡¡code¡¡block¡£¡¡It¡¡is¡¡important¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡to¡¡understand¡¡that¡¡an¡¡exclusive¡¡lock¡¡grants¡¡access¡¡to¡¡code£»¡¡not¡¡data£»¡¡but¡¡that¡¡code¡¡could¡¡access¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡data¡£¡¡And¡¡because¡¡only¡¡one¡¡thread¡¡is¡¡accessing¡¡the¡¡code£»¡¡it¡¡is¡¡implied¡¡that¡¡only¡¡one¡¡thread¡¡can¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡access¡¡the¡¡data¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡following¡¡is¡¡an¡¡example¡¡of¡¡code¡¡that¡¡uses¡¡exclusive¡¡locks¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡£¡¡¡£¡¡¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Module¡¡ThreadProblem¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©¡¡=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Task1£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡SyncLock¡¡elements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡elements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Next¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡SyncLock¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Task2£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡SyncLock¡¡elements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡SyncLock¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Main£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Module¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡bolded¡¡lines¡¡use¡¡the¡¡SyncLock¡¡and¡¡End¡¡SyncLock¡¡keywords£»¡¡which¡¡represent¡¡a¡¡code¡¡block¡¡of¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡exclusive¡¡access¡£¡¡The¡¡thread¡¡is¡¡granted¡¡access¡¡to¡¡only¡¡a¡¡single¡¡code¡¡block¡¡in¡¡each¡¡instance¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Looking¡¡at¡¡the¡¡code¡¡within¡¡the¡¡block£»¡¡you¡¡can¡¡see¡¡that¡¡the¡¡collection¡¡