久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

VB.net學(xué)習(xí)筆記(二十八)線程同步下

 龍門過(guò)客棧 2017-11-17


    3、ReaderWriterLock 類
    ReaderWriterLock定義了實(shí)現(xiàn)單寫程序和多寫程序語(yǔ)義的鎖,。ReaderWriterLock類中4個(gè)主要的方法
· AcquireReacJerLock():獲得-個(gè)讀程序鎖,,超時(shí)值使用一個(gè)整數(shù)或一個(gè) TimeSpan。
· AcquireWiiterLock():     獲得一個(gè)寫程序鎖,,超時(shí)值使用一個(gè)整數(shù)或一個(gè) TimeSpan,。
· ReleaseReaderLock():釋放讀程序鎖。
· ReleaseWriterLock():   釋放寫程序鎖,。
    一個(gè)線程可以持有讀線程鎖或?qū)懢€程鎖,,但是不能同時(shí)持有兩者。

  1. Imports System.Threading  
  2. Namespace AReadWriteLock  
  3.     Public Class ReadWrite  
  4.         Private rwl As ReaderWriterLock  
  5.         Private x As Integer  
  6.         Private y As Integer  
  7.         Public Sub New()  
  8.             rwl = New ReaderWriterLock()  
  9.         End Sub  
  10.         Public Sub ReadInts(ByRef a As Integer, ByRef b As Integer)  
  11.             rwl.AcquireReaderLock(Timeout.Infinite)  
  12.             Try  
  13.                 a = x  
  14.                 b = y  
  15.             Finally  
  16.                 rwl.ReleaseReaderLock()  
  17.             End Try  
  18.         End Sub  
  19.         Public Sub WriteInts(ByVal a As Integer, ByVal b As Integer)  
  20.             rwl.AcquireWriterLock(Timeout.Infinite)  
  21.             Try  
  22.                 x = a  
  23.                 y = b  
  24.                 Console.WriteLine(" x=" & x & " y=" & y & " ThreadID=" & Thread.CurrentThread.GetHashCode.ToString)  
  25.             Finally  
  26.                 rwl.ReleaseWriterLock()  
  27.             End Try  
  28.         End Sub  
  29.     End Class  
  30.     Public Class RWApp  
  31.         Private rw As New ReadWrite  
  32.         Public Overloads Shared Sub Main(ByVal args() As String)  
  33.             Dim e As New RWApp()  
  34.             Dim wt1 As New Thread(New ThreadStart(AddressOf e.Write))  
  35.             wt1.Start()  
  36.             Dim wt2 As New Thread(New ThreadStart(AddressOf e.Write))  
  37.             wt2.Start()  
  38.             Dim rt1 As New Thread(New ThreadStart(AddressOf e.Read))  
  39.             rt1.Start()  
  40.             Dim rt2 As New Thread(New ThreadStart(AddressOf e.Read))  
  41.             rt2.Start()  
  42.             Console.ReadLine()  
  43.         End Sub  
  44.         Private Sub Write()  
  45.             Dim a As Integer = 10  
  46.             Dim b As Integer = 11  
  47.             Console.WriteLine("=== Write ID:" & Thread.CurrentThread.GetHashCode.ToString)  
  48.             For i As Integer = 0 To 2  
  49.                 rw.WriteInts(a, b)  
  50.                 a += 1  
  51.                 b += 1  
  52.                 Thread.Sleep(1000)  
  53.             Next i  
  54.         End Sub  
  55.         Private Sub Read()  
  56.             Dim a As Integer = 10  
  57.             Dim b As Integer = 11  
  58.             Console.WriteLine("=== Read ID:" & Thread.CurrentThread.GetHashCode.ToString)  
  59.             For i As Integer = 0 To 2  
  60.                 rw.ReadInts(a, b)  
  61.                 Console.WriteLine("For i=" & i & " a=" & a & ” b=” & b & " ThreadID=" & Thread.CurrentThread.GetHashCode.ToString)  
  62.                 Thread.Sleep(1000)  
  63.             Next i  
  64.         End Sub  
  65.     End Class  
  66. End Namespace  
     線程的讀鎖或?qū)戞i同一時(shí)間只能有一個(gè)進(jìn)入,,結(jié)果如下:
              

   (三)手控同步
      System.Threading命名空間的一些可以用做手控同步的類,。它們賦予了程序員使用類似于WIN32線程API的低級(jí)線程API創(chuàng)建和管理多線程應(yīng)用程序的能力。如:Auto ResetEvent類,、ManualResetEvent類,、Mutex類、Interlocked類,。
     1,、ManualResetEvent類
       通知一個(gè)或多個(gè)正在等待的線程已發(fā)生事件,根據(jù)這個(gè)信號(hào)正在等待的線程決定是否繼續(xù)向下運(yùn)行,。ManualResetEvent對(duì)象只能擁有兩種狀態(tài):有信號(hào)(True)或無(wú)信號(hào)(False),。
      ManualResetEvent 就象燈塔的信號(hào)燈,作用是阻塞一個(gè)或多個(gè)線程,直到收到一個(gè)信號(hào)告訴ManualResetEvent不要再阻塞當(dāng)前的線程,。
  如果有信號(hào),,船只一路暢通無(wú)阻,當(dāng)前線程勇往直前運(yùn)行,,即使遇WaitOne也繼續(xù)前行,;
如果無(wú)信號(hào),船只一路遇礁則止,,當(dāng)前線程遇WaitOne則掛起受阻,。
             
  1. Imports System.Threading  
  2. Namespace NETThreadEvents  
  3.     Class AManualReset  
  4.         Shared LightSign As New ManualResetEvent(False) '1、無(wú)信號(hào)  
  5.         Shared Sub main()  
  6.             Dim t(4) As Thread  
  7.             For i As Integer = 0 To 3  
  8.                 t(i) = New Thread(AddressOf RunOrWait)  
  9.                 t(i).Start()  
  10.             Next  
  11.             'LightSign.Set()                '3,、恢復(fù)有信號(hào),線程甩開阻礙繼續(xù)暢通向前運(yùn)行  
  12.             Console.Read()  
  13.         End Sub  
  14.         Public Shared Sub RunOrWait()  
  15.             Console.WriteLine("ID " & Thread.CurrentThread.GetHashCode.ToString & " waiting... ")  
  16.             LightSign.WaitOne()                  '2,、無(wú)信號(hào)時(shí)線程掛起受阻,,有信號(hào)則暢通  
  17.             Console.WriteLine("ID " & Thread.CurrentThread.GetHashCode.ToString & "Running... not blocked!")  
  18.         End Sub  
  19.     End Class  
  20. End Namespace  
      說(shuō)明:左圖:1處設(shè)置為False,指示線程遇WaitOne受阻掛起,,所以在RunOrWait()方法(2處)的WaitOne時(shí)就掛起了,。中圖:1處設(shè)置為True,,線程暢通,2處WaiOne直接通過(guò),。右圖:1處為false無(wú)信號(hào),,所以在2處受阻,但是由于3處加了一句Set,,讓信號(hào)亮起,,前面掛起的恢復(fù)通過(guò),沒掛起當(dāng)然也通過(guò),。圖中可以看出10-12線程受阻,,由于主線程Set恢復(fù)信號(hào)后,原掛起的11,、12線程繼續(xù)跑起,,至于誰(shuí)搶到CPU由OS決定。
  
      注意:至于終結(jié)與未終結(jié),,MSDN:
     原文:Reset   Sets the state of the event to non-signaled, which causes threads to block. (Inherited from EventWaitHandle.)
     原譯文:Reset   將事件狀態(tài)設(shè)置為非終止?fàn)顟B(tài),,從而導(dǎo)致線程受阻。 (從 EventWaitHandle 繼承,。)
       因?yàn)閚on-signaled被翻譯成了未終止?fàn)顟B(tài),。把受阻線程設(shè)置成無(wú)信號(hào)事件狀態(tài)。

       2,、AutoResetEvent類
    通知正在等待的線程已發(fā)生事件,。處于等待狀態(tài)的線程,直到通過(guò)調(diào)用Set()方法將它置于信號(hào)通知狀態(tài),。
     AutoResetEvent和ManualResetEvent是類似的,。但有少些區(qū)別。
     AutoResetEvent和ManualResetEvent的區(qū)別:
(1) AutoResetEvent只會(huì)給一個(gè)線程發(fā)送信號(hào)(非全部),。ManualResetEvent給全部線程發(fā)信號(hào),。
(2) AutoResetEvent在set()后,會(huì)將線程狀態(tài)自動(dòng)置為false,。ManualResetEvent在Set()后,,線程的狀態(tài)就變?yōu)閠rue,必須手動(dòng)ReSet()之后,,才會(huì)重新將線程置為false,。
    所以ManualResetEvent就象大門(Sign)一打開(True),所有馬(Threads)都跑了,,且門一直開啟True,。AutoResetEvent只隨機(jī)開一匹的門(Set),放跑(True)后馬上關(guān)閉(False),。
  1. Imports System.Threading  
  2. Namespace NETThreadEvents  
  3.     Class AManualReset  
  4.         Shared LightSign As New AutoResetEvent(False) '1,、無(wú)信號(hào)  
  5.         Shared Sub main()  
  6.             Dim t(4) As Thread  
  7.             For i As Integer = 0 To 3  
  8.                 t(i) = New Thread(AddressOf RunOrWait)  
  9.                 t(i).Start()  
  10.             Next  
  11.             LightSign.Set()     '2,隨機(jī)釋放某一已經(jīng)阻塞的線程(不是全部)  
  12.             Console.Read()  
  13.         End Sub  
  14.         Public Shared Sub RunOrWait()  
  15.             Console.WriteLine("ID " & Thread.CurrentThread.GetHashCode.ToString & " waiting... ")  
  16.             LightSign.WaitOne()  
  17.             Console.WriteLine("ID " & Thread.CurrentThread.GetHashCode.ToString & "Running... not blocked!")  
  18.         End Sub  
  19.     End Class  
  20. End Namespace  
        說(shuō)明:Set后,,僅將一個(gè)線程變成True,所以 ID9線程通過(guò)了,,ID12仍然阻塞.
                  

      3,、Mutex類(mutex互斥)
       Mutex鎖提供了交叉線程和交叉同步進(jìn)程。如果沒有線程擁有有信號(hào)狀態(tài),,Mutex的狀態(tài)就會(huì)被置為有信號(hào)狀態(tài),。Mutex并不具有Monitor類的所有等待和脈沖功能,不過(guò)它確實(shí)提供了能夠在進(jìn)程之間使用的命名互斥體(使用重載 構(gòu)造函數(shù))的創(chuàng)建,。使用Mutex類優(yōu)于Monitor類的是:Mutex類可跨進(jìn)程使用,,而Monitor類則不行。
      Mutex(boolean initiallyOwned, string name) 初始化 Mutex 類的新實(shí)例,。
              initiallyOwned: 若為 true,,調(diào)用端擁有互斥體的初始所屬權(quán);否則為 false,。
             Name:                  Mutex 的名稱,。如果值為 null,則 Mutex 是未命名的,。
  1. Imports System.Threading  
  2. Namespace AMutex  
  3.     Class NETMutex  
  4.         Private Shared myMutex As Mutex  
  5.         Public Shared Sub Main()  
  6.             myMutex = New Mutex(True, "Magic")  
  7.             Dim nm As New NETMutex  
  8.             Dim t As New Thread(New ThreadStart(AddressOf nm.Run))  
  9.             t.Start()  
  10.   
  11.   
  12.             Dim ID As String = Thread.CurrentThread.GetHashCode.ToString  
  13.             Console.WriteLine("ID:" & ID & " main thread will sleep for 3 seconds...")  
  14.             Thread.Sleep(3000)  
  15.             Console.WriteLine("ID:" & ID & ” main thread Woke Up")  
  16.   
  17.             myMutex.ReleaseMutex()  '1,、釋放互斥鎖(讓線程t中3處得到鎖,以便向下運(yùn)行)  
  18.             Console.WriteLine("ID:" & ID & " main Before WaitOne")  
  19.             myMutex.WaitOne()       '2,、阻塞,,直到再次得到互斥鎖(線程t中4處釋放鎖)  
  20.             Console.WriteLine("ID:" & ID & " main Lock. owned by Main Thread")  
  21.             Console.ReadLine()  
  22.         End Sub  
  23.         Public Sub Run()  
  24.             Dim ID As String = Thread.CurrentThread.GetHashCode.ToString  
  25.             Console.WriteLine("ID:" & ID & " t_thread In Run method")  
  26.             myMutex.WaitOne()       '3、阻塞線程t,直到得到互斥鎖),,1外釋放后,,這里通暢向下  
  27.             Console.WriteLine("ID:" & ID & " t_thread will sleep for 6 seconds")  
  28.             Thread.Sleep(6000)  
  29.   
  30.             Console.WriteLine("ID:" & ID & " t_thread end of Run method")  
  31.             myMutex.ReleaseMutex()  '4、此處必須釋放鎖,,否則2處會(huì)無(wú)限等待鎖(最后拋出異常)  
  32.         End Sub  
  33.     End Class  
  34. End Namespace  
       說(shuō)明: 主線程創(chuàng)建互斥鎖后,,擁有該鎖,等待3秒后在1處釋放鎖,,以便讓線程t擁有鎖后(3處)繼續(xù)向下運(yùn)行,,直到釋放鎖(4處),釋放后主線程馬上得到鎖并在阻塞的2處繼續(xù)向下運(yùn)行,。4處必須釋放原因:MSDN: 在桌面的 .NET 中,,如果沒有線程擁有互斥體,則互斥體的狀態(tài)為終止并將在下一個(gè)獲取互斥體的線程中引發(fā) AbandonedMutexException,。
         

     4,、Intelocked類
      Interlocked類為原子操作,在多個(gè)線程之間共享的非阻塞整數(shù)更新提供了方法。如果變量位于共享的內(nèi)存中的話,,不同進(jìn)程的線程以使用這種機(jī)制。
原子操作,,即不可分割操作,,一個(gè)線程操作時(shí),不會(huì)切換到另一個(gè)操作,??珊?jiǎn)單理解為獨(dú)占模式。

      Interlocked可以為多個(gè)線程共享的變量提供原子操作:
Interlocked.Increment:以原子操作的形式遞增指定變量的值并存儲(chǔ)結(jié)果,。
Interlocked.Decrement  以原子操作的形式遞減指定變量的值并存儲(chǔ)結(jié)果,。
Interlocked.Add               以原子操作的形式,添加兩個(gè)整數(shù)并用兩者的和替換第一個(gè)整數(shù)

    注意:Intelocked原子操作鎖定的是某一個(gè)值,,僅在類似上面三句中生效,,越過(guò)此句原子操作失效。

  1. Imports System.Threading  
  2. Namespace AInterLocker  
  3.     Class WinterLocked  
  4.         Public a As New ManualResetEvent(False)  
  5.         Private i As Integer = 5  
  6.         Public Sub Run(ByVal s As Object)  
  7.             Interlocked.Increment(i)   '2,、原子操作遞增  
  8.             Console.WriteLine(Thread.CurrentThread.GetHashCode.ToString & "   " & i)  
  9.             Thread.Sleep(500)  
  10.             'Console.WriteLine(Thread.CurrentThread.GetHashCode.ToString & " completed")  ‘3,、非原子操作  
  11.         End Sub  
  12.         Public Function GetValue() As Integer  
  13.             Return i  
  14.         End Function  
  15.     End Class  
  16.     Public Class MainApp  
  17.         Public Shared Sub Main()  
  18.             Dim mR As New ManualResetEvent(False)  
  19.             Dim wL As New WinterLocked  
  20.   
  21.             For i As Integer = 1 To 10   '1、線程池排隊(duì)  
  22.                 ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf wL.Run), 2)  
  23.             Next i  
  24.             mR.WaitOne(3000, True)       '在3秒后退出同步域  
  25.             Console.WriteLine("Result of 10 times is " & wL.GetValue)  
  26.             Console.ReadLine()  
  27.         End Sub  
  28.     End Class  
  29. End Namespace  
      說(shuō)明:下面左右兩圖都是上面的結(jié)果,,特別是左圖,,為啥會(huì)出現(xiàn)兩個(gè)11,而少了10呢,?首先確認(rèn)10個(gè)線程進(jìn)入后是進(jìn)行了原子操作,,每個(gè)線程增加1,因?yàn)?0個(gè)線程的結(jié)果都是15(=5+10),,因?yàn)樵硬僮鲀H在2處,,過(guò)了此句后面的都不是原子操作。細(xì)節(jié)為:A線程原子鎖定i(=9),,然后增加1(i=10),,后而退出原子操作馬上要執(zhí)行后一句提取i值(但還沒顯示),這里B線程切換進(jìn)來(lái),原子鎖定i并對(duì)i增加1(i=10+1=11),,然后原子操作退出并提取i值到B線程中,。注意A、B線程提取的i值都是11,,故顯示的都是11,,至于中間的12則是在輸出過(guò)程中一樣是要花費(fèi)時(shí)間的,被另一線程C切入并提取i值12,,并于B線程前輸出,。在3處增加一句顯示i的結(jié)果,上面的效果將更加明顯,。
      

      5,、共享變量、方法和同步
      共享(Shared)的變量和方法,,既可以被類訪問也可被該類的實(shí)例訪問,,所以同步鎖定Shared的變量或方法就被應(yīng)用到整個(gè)該類上。此時(shí),,其它對(duì)象不允許使用此類的Shared變量或方法,。

      ThreadStaticAttribute 類
         帶有ThreadStaticAttribute 的Shared變量,對(duì)每個(gè)訪問變量的線程都會(huì)有一個(gè)同一變量的單獨(dú)副本,。意味著如果一個(gè)線程修改了變量,,另一個(gè)訪問變量的線程就不能看到這些變化(包括主線程)。這種行為是有背于Shared變量的默認(rèn)行為的,。用處比如web應(yīng)用中,每個(gè)請(qǐng)求都是一個(gè)獨(dú)立的線程,如果我們希望將一個(gè)值作為靜態(tài)字段全局使用,同時(shí)又不想影響其他用戶,這時(shí)候一般我們是使用Session的,。

  1. Imports System.Threading  
  2. Namespace TestShared  
  3.     Class AThreadStatic  
  4.         <ThreadStatic> Public Shared x As Integer  '1、共享變量,,各線程分別有副本x  
  5.         Public Shared y As Integer = 1             '2、共享變量,,各線程無(wú)副本  
  6.         Public Sub Run()  
  7.             For i As Integer = 1 To 5  
  8.                 Dim id As String = Thread.CurrentThread.GetHashCode.ToString  
  9.                 x += 1  
  10.                 y += 1  
  11.                 Console.WriteLine("i=" & i & “ ThreadID=" & id & " x=" & x & " y=" & y)  
  12.                 Thread.Sleep(1000)                 '3.共5次循環(huán),,花時(shí)5秒  
  13.             Next i  
  14.         End Sub  
  15.     End Class  
  16.     Public Class MainApp  
  17.         Public Shared Sub Main()  
  18.             Dim tS As New AThreadStatic  
  19.             Dim tl As New Thread(New ThreadStart(AddressOf tS.Run))  
  20.             Dim t2 As New Thread(New ThreadStart(AddressOf tS.Run))  
  21.             tl.Start()  
  22.             t2.Start()  
  23.             Thread.Sleep(3500)                     '4、在3.5秒后,,看一下類中共享變量值  
  24.             Console.WriteLine("Main thread get value1:" & AThreadStatic.x & " " & AThreadStatic.y)  
  25.             Thread.Sleep(4000)                     '5、又4秒后,,看一下類中共享變量值  
  26.             Console.WriteLine("Main thread get value2:" & AThreadStatic.x & " " & AThreadStatic.y)  
  27.             Console.ReadLine()  
  28.         End Sub  
  29.     End Class  
  30. End Namespace  
      說(shuō)明:x被標(biāo)注后,,在兩個(gè)線程中將分別生成各自的x的副本(并不影響原類的值),所以在4處可以看到原類中x仍為0,,但y沒被標(biāo)注,,所以值是變化的。最后的結(jié)果(5處),,也可以看出始終x沒被修改為0(僅在各自的線程中修改其副本),y是修改的為11,。
       

     (四)防止死鎖
        線程越多,,上鎖越復(fù)雜,,就越容易死鎖,。通常的防止的原則就是:一個(gè)線程最多只能有一個(gè)鎖,。
         如果想更多的鎖,,就越容易死鎖,。例如:A線程中擁有鎖L1期待鎖L2,;而B線程中擁有鎖L2期待鎖L1,;如果兩個(gè)同時(shí)發(fā)生或重疊,就會(huì)發(fā)生死鎖,。當(dāng)然如果時(shí)間錯(cuò)過(guò)也就無(wú)所謂。
  1. Imports System.Threading  
  2. Namespace DeadLock  
  3.     Class DL  
  4.         Private field_1 As Integer = 0  
  5.         Private field_2 As Integer = 0  
  6.         Private lock_1 As Object = New Integer(1) {}  
  7.         Private lock_2 As Object = New Integer(1) {}  
  8.         Public Sub first(ByVal val As Integer)  
  9.             SyncLock lock_1  
  10.                 Console.WriteLine("First:Acquired lock_1:" & Thread.CurrentThread.GetHashCode.ToString + " Now Sleeping")  
  11.                 Thread.Sleep(1000)  
  12.                 SyncLock lock_2  
  13.                     Console.WriteLine("First:Acquired lock_2:" & Thread.CurrentThread.GetHashCode.ToString)  
  14.                     field_1 = val  
  15.                     field_2 = val  
  16.                 End SyncLock  
  17.             End SyncLock  
  18.         End Sub  
  19.         Public Sub second(ByVal val As Integer)  
  20.             SyncLock lock_2  
  21.                 Console.WriteLine("Second:Acquired lock_2:" & Thread.CurrentThread.GetHashCode.ToString)  
  22.                 SyncLock lock_1  
  23.                     Console.WriteLine("Second:Acquired lock I:" & Thread.CurrentThread.GetHashCode().ToString)  
  24.                     field_1 = val  
  25.                     field_2 = val  
  26.                 End SyncLock  
  27.             End SyncLock  
  28.         End Sub  
  29.     End Class  
  30.     Public Class MainApp  
  31.         Private d As New DL()  
  32.         Public Shared Sub Main()  
  33.             Dim m As New MainApp  
  34.             Dim tl As New Thread(New ThreadStart(AddressOf m.Run1))  
  35.             tl.Start()  
  36.             Dim t2 As New Thread(New ThreadStart(AddressOf m.Run2))  
  37.             t2.Start()  
  38.             Console.ReadLine()  
  39.         End Sub  
  40.         Public Sub Run1()  
  41.             d.first(10)  
  42.         End Sub  
  43.         Public Sub Run2()  
  44.             d.second(10)  
  45.         End Sub  
  46.     End Class  
  47. End Namespace  
      說(shuō)明:兩個(gè)線程都分別擁有鎖,,還期待對(duì)方向的鎖,,都處于等待對(duì)方的鎖,,于是就死鎖了,。
       


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多