Pernyataan SyncLock

Memperoleh kunci eksklusif untuk blok pernyataan sebelum mengeksekusi blok.

Sintaks

SyncLock lockobject  
    [ block ]  
End SyncLock  

Generator

lockobject
Harus diisi. Ekspresi yang mengevaluasi ke referensi objek.

block
Opsional. Blok pernyataan yang akan dieksekusi ketika kunci diperoleh.

End SyncLock
Mengakhiri SyncLock blok.

Keterangan

Pernyataan SyncLock memastikan bahwa beberapa utas tidak mengeksekusi blok pernyataan pada saat yang bersamaan. SyncLock mencegah setiap utas memasuki blok sampai tidak ada utas lain yang menjalankannya.

Penggunaan paling umum dari SyncLock adalah untuk melindungi data agar tidak diperbarui oleh lebih dari satu utas secara bersamaan. Jika pernyataan yang memanipulasi data harus diselesaikan tanpa gangguan, masukkan ke dalam blok SyncLock.

Blok pernyataan yang dilindungi oleh kunci eksklusif terkadang disebut bagian kritis .

Aturan

  • Percabangan. Anda tidak dapat bercabang menjadi SyncLock blok dari luar blok.

  • Kunci Nilai Objek. Nilai lockobject tidak boleh Nothing. Anda harus membuat objek kunci sebelum menggunakannya dalam pernyataan SyncLock.

    Anda tidak dapat mengubah nilai lockobject saat menjalankan blok SyncLock. Mekanismenya mengharuskan objek kunci tetap tidak berubah.

  • Anda tidak dapat menggunakan operator Menunggu di blok SyncLock.

Perilaku

  • Mekanisme. Saat utas mencapai pernyataan SyncLock, utas mengevaluasi ekspresi lockobject dan menangguhkan eksekusi hingga memperoleh kunci eksklusif pada objek yang dikembalikan oleh ekspresi. Ketika utas lain mencapai pernyataan SyncLock, itu tidak memperoleh kunci sampai utas pertama mengeksekusi pernyataan End SyncLock.

  • Data yang Dilindungi. Jika lockobject adalah variabel Shared, kunci eksklusif mencegah utas dalam setiap instance kelas dari mengeksekusi blok SyncLock saat utas lain menjalankannya. Ini melindungi data yang dibagikan di antara semua instance.

    Jika lockobject adalah variabel instans (bukan Shared ), kunci mencegah utas yang berjalan di instans saat ini mengeksekusi blok SyncLock pada saat yang sama dengan utas lain dalam instans yang sama. Ini melindungi data yang dikelola oleh instance individu.

  • Akuisisi dan Pelepasan. Blok SyncLock berperilaku seperti konstruksi Try...Finally di mana blok Try memperoleh kunci eksklusif pada lockobject dan blok Finally melepaskannya. Karena itu, SyncLock blok menjamin pelepasan kunci, tidak peduli bagaimana Anda keluar dari blok. Ini benar bahkan dalam kasus pengecualian yang tidak ditangani.

  • Panggilan Kerangka. SyncLock memperoleh dan melepaskan kunci eksklusif dengan memanggil metode Enter dan Exit dari kelas Monitor di ruang nama System.Threading.

Praktek Pemrograman

lockobject harus selalu mengevaluasi ke objek yang dimiliki secara eksklusif oleh kelas Anda. Anda harus mendeklarasikan variabel objek Private untuk melindungi data milik instance saat ini, atau variabel objek Private Shared untuk melindungi data yang umum untuk semua instance.

Anda tidak boleh menggunakan kata kunci Me untuk menyediakan objek kunci sebagai contoh data. Jika kode di luar kelas Anda memiliki referensi ke instance kelas Anda, kode tersebut dapat menggunakan referensi itu sebagai objek kunci untuk blok SyncLock yang sama sekali berbeda dari milik Anda, melindungi data yang berbeda. Dengan cara ini, kelas Anda dan kelas lain dapat saling memblokir agar tidak mengeksekusi blok SyncLock yang tidak terkait. Demikian pula penguncian pada string dapat menjadi masalah karena kode lain dalam proses yang menggunakan string yang sama akan berbagi kunci yang sama.

Anda juga tidak boleh menggunakan metode Me.GetType untuk menyediakan objek kunci untuk data bersama. Ini karena GetType selalu mengembalikan objek Type yang sama untuk nama kelas yang diberikan. Kode eksternal dapat memanggil GetType di kelas Anda dan mendapatkan objek kunci yang sama dengan yang Anda gunakan. Ini akan mengakibatkan dua kelas saling memblokir dari SyncLock blok mereka.

Contoh

Deskripsi

Contoh berikut menunjukkan kelas yang memelihara daftar pesan sederhana. Ini menyimpan pesan dalam array dan elemen yang terakhir digunakan dari array itu dalam sebuah variabel. Prosedur addAnotherMessage menambah elemen terakhir dan menyimpan pesan baru. Kedua operasi tersebut dilindungi oleh pernyataan SyncLock dan End SyncLock, karena setelah elemen terakhir ditambahkan, pesan baru harus disimpan sebelum utas lain dapat menambahkan elemen terakhir lagi.

Jika kelas simpleMessageList berbagi satu daftar pesan di antara semua instance-nya, variabel messagesList dan messagesLast akan dideklarasikan sebagai Shared. Dalam hal ini, variabel messagesLock juga harus Shared, sehingga akan ada satu objek kunci yang digunakan oleh setiap instance.

Kode

Class simpleMessageList
    Public messagesList() As String = New String(50) {}
    Public messagesLast As Integer = -1
    Private messagesLock As New Object
    Public Sub addAnotherMessage(ByVal newMessage As String)
        SyncLock messagesLock
            messagesLast += 1
            If messagesLast < messagesList.Length Then
                messagesList(messagesLast) = newMessage
            End If
        End SyncLock
    End Sub
End Class

Deskripsi

Contoh berikut menggunakan utas dan SyncLock. Selama pernyataan SyncLock ada, blok pernyataan adalah bagian kritis dan balance tidak pernah menjadi bilangan negatif. Anda dapat mengomentari pernyataan SyncLock dan End SyncLock untuk melihat efek dari mengabaikan kata kunci SyncLock.

Kode

Imports System.Threading

Module Module1

    Class Account
        Dim thisLock As New Object
        Dim balance As Integer

        Dim r As New Random()

        Public Sub New(ByVal initial As Integer)
            balance = initial
        End Sub

        Public Function Withdraw(ByVal amount As Integer) As Integer
            ' This condition will never be true unless the SyncLock statement
            ' is commented out:
            If balance < 0 Then
                Throw New Exception("Negative Balance")
            End If

            ' Comment out the SyncLock and End SyncLock lines to see
            ' the effect of leaving out the SyncLock keyword.
            SyncLock thisLock
                If balance >= amount Then
                    Console.WriteLine("Balance before Withdrawal :  " & balance)
                    Console.WriteLine("Amount to Withdraw        : -" & amount)
                    balance = balance - amount
                    Console.WriteLine("Balance after Withdrawal  :  " & balance)
                    Return amount
                Else
                    ' Transaction rejected.
                    Return 0
                End If
            End SyncLock
        End Function

        Public Sub DoTransactions()
            For i As Integer = 0 To 99
                Withdraw(r.Next(1, 100))
            Next
        End Sub
    End Class

    Sub Main()
        Dim threads(10) As Thread
        Dim acc As New Account(1000)

        For i As Integer = 0 To 9
            Dim t As New Thread(New ThreadStart(AddressOf acc.DoTransactions))
            threads(i) = t
        Next

        For i As Integer = 0 To 9
            threads(i).Start()
        Next
    End Sub

End Module

Komentar

Lihat juga