Saya memiliki beberapa pertanyaan tentang penggunaan dan pentingnya synchronized
kata kunci.
- Apa arti penting dari
synchronized
kata kunci? - Kapan metode seharusnya
synchronized
? - Apa artinya secara terprogram dan logis?
java
multithreading
keyword
synchronized
Johanna
sumber
sumber
Jawaban:
Kata
synchronized
kunci adalah semua tentang utas yang berbeda membaca dan menulis ke variabel, objek dan sumber daya yang sama. Ini bukan topik sepele di Jawa, tapi di sini ada kutipan dari Sun:Singkatnya, ketika Anda memiliki dua utas yang membaca dan menulis ke 'sumber' yang sama, ucapkan variabel bernama
foo
, Anda perlu memastikan bahwa utas ini mengakses variabel dengan cara atom. Tanpasynchronized
kata kunci, utas 1 Anda mungkin tidak melihat utas perubahan 2 dibuatfoo
, atau lebih buruk, itu hanya mungkin setengah diubah. Ini tidak akan seperti yang Anda harapkan secara logis.Sekali lagi, ini adalah topik non-sepele di Jawa. Untuk mempelajari lebih lanjut, jelajahi topik di sini di SO dan Jalinan tentang:
Terus jelajahi topik ini sampai nama "Brian Goetz" secara permanen dikaitkan dengan istilah "konkurensi" di otak Anda.
sumber
Yah, saya pikir kita sudah punya cukup penjelasan teoretis, jadi pertimbangkan kode ini
Catatan:
synchronized
memblokir panggilan utas berikutnya ke metode pengujian () selama eksekusi utas sebelumnya tidak selesai. Utas dapat mengakses metode ini satu per satu. Tanpasynchronized
semua utas dapat mengakses metode ini secara bersamaan.Ketika sebuah thread memanggil metode yang disinkronkan 'tes' dari objek (di sini objek adalah turunan dari kelas 'TheDemo') ia mendapatkan kunci dari objek itu, setiap utas baru tidak dapat memanggil SETIAP metode yang disinkronkan dari objek yang sama selama utas sebelumnya yang telah memperoleh kunci tidak melepaskan kunci.
Hal serupa terjadi ketika metode sinkronisasi kelas statis dipanggil. Utas mendapatkan kunci yang terkait dengan kelas (dalam hal ini metode disinkronkan non statis dari instance kelas itu dapat dipanggil oleh utas apa pun karena kunci tingkat objek masih tersedia). Utas lain tidak akan dapat memanggil metode sinkronisasi statis apa pun dari kelas selama kunci tingkat kelas tidak dilepaskan oleh utas yang saat ini memegang kunci.
Output dengan disinkronkan
Output tanpa disinkronkan
sumber
synchronized
, tetapi konsistensi memori diabaikan.Kata
synchronized
kunci mencegah akses bersamaan ke blok kode atau objek dengan beberapa utas. Semua metodeHashtable
adalahsynchronized
, jadi hanya satu utas yang dapat menjalankan salah satu dari mereka sekaligus.Saat menggunakan non-
synchronized
konstruk likeHashMap
, Anda harus membangun fitur keamanan-ulir dalam kode Anda untuk mencegah kesalahan konsistensi.sumber
synchronized
berarti bahwa dalam lingkungan multi-ulir, objek yang memilikisynchronized
metode / blok tidak memungkinkan dua utas untuk mengaksessynchronized
metode / blok kode pada saat yang sama. Ini berarti bahwa satu utas tidak dapat membaca sementara utas lainnya memperbaruinya.Utas kedua sebagai gantinya akan menunggu sampai utas pertama menyelesaikan eksekusi. Overhead adalah kecepatan, tetapi keuntungannya dijamin konsistensi data.
Jika aplikasi Anda menggunakan satu utas,
synchronized
blok tidak memberikan manfaat.sumber
Kata
synchronized
kunci menyebabkan utas untuk mendapatkan kunci ketika memasukkan metode, sehingga hanya satu utas yang dapat menjalankan metode pada saat yang sama (untuk contoh objek yang diberikan, kecuali itu adalah metode statis).Ini sering disebut membuat class-safe, tetapi saya akan mengatakan ini adalah eufemisme. Memang benar bahwa sinkronisasi melindungi keadaan internal vektor agar tidak rusak, ini biasanya tidak banyak membantu pengguna vektor.
Pertimbangkan ini:
Meskipun metode yang terlibat disinkronkan, karena mereka sedang dikunci dan dibuka secara terpisah, dua untaian yang sayangnya waktunya dapat membuat vektor dengan dua elemen.
Jadi sebenarnya, Anda harus menyinkronkan dalam kode aplikasi Anda juga.
Karena sinkronisasi tingkat metode adalah a) mahal ketika Anda tidak membutuhkannya dan b) tidak cukup ketika Anda membutuhkan sinkronisasi, sekarang ada penggantian yang tidak disinkronkan (ArrayList dalam kasus Vektor).
Baru-baru ini, paket konkurensi telah dirilis, dengan sejumlah utilitas pintar yang menangani masalah multi-threading.
sumber
Gambaran
Kata kunci yang disinkronkan di Jawa berkaitan dengan keamanan utas, yaitu ketika beberapa utas membaca atau menulis variabel yang sama.
Ini dapat terjadi secara langsung (dengan mengakses variabel yang sama) atau tidak langsung (dengan menggunakan kelas yang menggunakan kelas lain yang mengakses variabel yang sama).
Kata kunci yang disinkronkan digunakan untuk menentukan blok kode di mana banyak utas dapat mengakses variabel yang sama dengan cara yang aman.
Lebih dalam
Sintaks
synchronized
kata kunci mengambilObject
parameter seperti itu (disebut objek kunci ), yang kemudian diikuti oleh a{ block of code }
.Ketika eksekusi menemukan kata kunci ini, utas saat ini mencoba untuk "mengunci / memperoleh / memiliki" (pilih) objek kunci dan jalankan blok kode yang terkait setelah kunci diperoleh.
Setiap penulisan ke variabel di dalam blok kode yang disinkronkan dijamin akan terlihat oleh setiap utas lain yang juga mengeksekusi kode di dalam blok kode yang disinkronkan menggunakan objek kunci yang sama .
Hanya satu utas pada satu waktu yang dapat menahan kunci, selama itu semua utas lainnya yang mencoba mendapatkan objek kunci yang sama akan menunggu (jeda eksekusi mereka). Kunci akan dilepaskan ketika eksekusi keluar dari blok kode yang disinkronkan.
Metode yang disinkronkan:
Menambahkan
synchronized
kata kunci ke definisi metode sama dengan seluruh badan metode yang dibungkus dengan blok kode yang disinkronkan dengan objek kunci menjadithis
(misalnya metode) danClassInQuestion.getClass()
(untuk metode kelas) .- Metode Instance adalah metode yang tidak memiliki
static
kata kunci.- Metode kelas adalah metode yang memiliki
static
kata kunci.Teknis
Tanpa sinkronisasi, itu tidak dijamin di mana urutan membaca dan menulis terjadi, mungkin meninggalkan variabel dengan sampah.
(Misalnya variabel bisa berakhir dengan setengah dari bit yang ditulis oleh satu utas dan setengah dari bit yang ditulis oleh utas lain, meninggalkan variabel dalam keadaan yang tak satu pun dari utas mencoba untuk menulis, tetapi kekacauan gabungan keduanya.)
Tidak cukup untuk menyelesaikan operasi penulisan di utas sebelumnya (waktu di dinding) utas lain membacanya, karena perangkat keras bisa saja menembolok nilai variabel, dan utas bacaan akan melihat nilai yang di-cache bukan apa yang dituliskan ke Itu.
Kesimpulan
Jadi dalam kasus Java, Anda harus mengikuti Java Memory Model untuk memastikan bahwa kesalahan threading tidak terjadi.
Dengan kata lain: Gunakan sinkronisasi, operasi atom atau kelas yang menggunakannya untuk Anda di bawah tenda.
sumber
Anggap saja semacam pintu pagar seperti yang mungkin Anda temukan di lapangan sepakbola. Ada steam paralel dari orang yang ingin masuk tetapi di pintu putar mereka 'disinkronkan'. Hanya satu orang pada satu waktu yang bisa melewati. Semua yang ingin melewati akan melakukannya, tetapi mereka mungkin harus menunggu sampai mereka bisa melewatinya.
sumber
Utas berkomunikasi terutama dengan berbagi akses ke bidang dan bidang referensi objek merujuk. Bentuk komunikasi ini sangat efisien, tetapi memungkinkan dua jenis kesalahan: interferensi utas dan kesalahan konsistensi memori . Alat yang diperlukan untuk mencegah kesalahan ini adalah sinkronisasi.
Blok atau metode yang disinkronkan mencegah interferensi utas dan memastikan bahwa data konsisten. Kapan saja, hanya satu utas yang dapat mengakses blok atau metode yang disinkronkan ( bagian kritis ) dengan memperoleh kunci. Utas lainnya akan menunggu pelepasan kunci untuk mengakses bagian kritis .
Metode disinkronkan ketika Anda menambahkan
synchronized
definisi atau deklarasi metode. Anda juga dapat menyinkronkan blok kode tertentu dengan-dalam metode.Ini berarti bahwa hanya satu utas yang dapat mengakses bagian kritis dengan memperoleh kunci. Kecuali jika utas ini melepaskan kunci ini, semua utas lainnya harus menunggu untuk mendapatkan kunci. Mereka tidak memiliki akses untuk masuk ke bagian kritis tanpa mendapatkan kunci.
Ini tidak bisa dilakukan dengan sihir. Merupakan tanggung jawab programmer untuk mengidentifikasi bagian-bagian penting dalam aplikasi dan menjaganya sesuai. Java menyediakan kerangka kerja untuk menjaga aplikasi Anda, tetapi di mana dan apa semua bagian yang harus dijaga adalah tanggung jawab programmer.
Lebih detail dari halaman dokumentasi java
Kunci dan Sinkronisasi Intrinsik:
Setiap objek memiliki kunci intrinsik yang terkait dengannya . Dengan konvensi, utas yang memerlukan akses eksklusif dan konsisten ke bidang objek harus memperoleh kunci intrinsik objek sebelum mengaksesnya, dan kemudian melepaskan kunci intrinsik ketika dilakukan dengan mereka.
Sebuah thread dikatakan memiliki kunci intrinsik antara waktu kunci tersebut diperoleh dan melepaskan kunci tersebut. Selama utas memiliki kunci intrinsik, tidak ada utas lain yang bisa mendapatkan kunci yang sama. Utas lainnya akan memblokir ketika mencoba untuk mendapatkan kunci.
Membuat metode yang disinkronkan memiliki dua efek :
Ketika satu utas menjalankan metode yang disinkronkan untuk suatu objek, semua utas lainnya yang menjalankan metode yang disinkronkan untuk blok objek yang sama (menunda eksekusi) hingga utas pertama selesai dengan objek tersebut.
Ini menjamin bahwa perubahan keadaan objek terlihat oleh semua utas.
Cari alternatif lain untuk sinkronisasi di:
Hindari disinkronkan (ini) di Jawa?
sumber
Synchronized normal method
setara denganSynchronized statement
(gunakan ini)Synchronized static method
setara denganSynchronized statement
(gunakan kelas)Pernyataan tersinkronisasi (menggunakan variabel)
Karena
synchronized
, kami memiliki keduanyaSynchronized Methods
danSynchronized Statements
. Namun,Synchronized Methods
mirip dengan ituSynchronized Statements
jadi kita hanya perlu mengertiSynchronized Statements
.=> Pada dasarnya, kita akan memilikinya
Berikut adalah 2 pemikiran yang membantu pemahaman
synchronized
intrinsic lock
keterkaitan dengannya.synchronized statement
, secara otomatis memperolehintrinsic lock
untuk itusynchronized statement's
objek dan rilis ketika metode kembali. Selama utas memilikiintrinsic lock
, TIDAK ada utas lain yang dapat memperoleh kunci SAMA => aman.=> Ketika
thread A
memanggilsynchronized(this){// code 1}
=> semua kode blok (kelas dalam) di mana memilikisynchronized(this)
dan semuasynchronized normal method
(kelas dalam) dikunci karena kunci SAMA . Ini akan dieksekusi setelahthread A
membuka kunci ("// kode 1" selesai).Perilaku ini mirip dengan
synchronized(a variable){// code 1}
atausynchronized(class)
.SAMA KUNCI => kunci (tidak bergantung pada metode mana? Atau pernyataan mana?)
Gunakan metode yang disinkronkan atau pernyataan yang disinkronkan?
Saya lebih suka
synchronized statements
karena lebih bisa diperpanjang. Contoh, di masa depan, Anda hanya perlu menyinkronkan bagian dari metode. Contoh, Anda memiliki 2 metode yang disinkronkan dan tidak memiliki yang relevan satu sama lain, namun ketika sebuah thread menjalankan metode, itu akan memblokir metode lain (itu dapat mencegah dengan menggunakansynchronized(a variable)
).Namun, menerapkan metode yang disinkronkan adalah sederhana dan kode terlihat sederhana. Untuk beberapa kelas, hanya ada 1 metode yang disinkronkan, atau semua metode yang disinkronkan di kelas yang relevan satu sama lain => kita dapat menggunakan
synchronized method
untuk membuat kode lebih pendek dan mudah dimengertiCatatan
(itu tidak relevan dengan banyak
synchronized
hal, itu adalah perbedaan antara objek dan kelas atau tidak ada yang statis dan statis).synchronized
atau metode normal atausynchronized(this)
atausynchronized(non-static variable)
akan disinkronkan berdasarkan pada setiap instance objek.synchronized
atau metode statissynchronized(class)
atausynchronized(static variable)
akan disinkronkan berdasarkan kelasReferensi
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Semoga ini bisa membantu
sumber
Berikut ini penjelasan dari The Java Tutorials .
Pertimbangkan kode berikut:
sumber
Untuk pemahaman saya disinkronkan pada dasarnya berarti bahwa kompiler menulis monitor.enter dan monitor.exit di sekitar metode Anda. Karena itu mungkin thread aman tergantung pada bagaimana digunakan (maksud saya adalah Anda dapat menulis objek dengan metode yang disinkronkan bukan threadsafe tergantung pada apa yang kelas Anda lakukan).
sumber
Apa yang tidak ada jawaban lain adalah salah satu aspek penting: hambatan memori . Sinkronisasi utas pada dasarnya terdiri dari dua bagian: serialisasi dan visibilitas. Saya menyarankan semua orang ke google untuk "jvm memory barrier", karena ini adalah topik yang tidak sepele dan sangat penting (jika Anda memodifikasi data bersama yang diakses oleh banyak utas). Setelah melakukan itu, saya menyarankan melihat kelas paket java.util.concurrent yang membantu untuk menghindari menggunakan sinkronisasi eksplisit, yang pada gilirannya membantu menjaga program sederhana dan efisien, bahkan mungkin mencegah kebuntuan.
Salah satu contohnya adalah ConcurrentLinkedDeque . Bersama dengan pola perintah, ini memungkinkan untuk membuat utas pekerja yang sangat efisien dengan memasukkan perintah ke dalam antrian bersamaan - tidak diperlukan sinkronisasi eksplisit, tidak ada deadlock yang mungkin, tidak ada sleep eksplisit () diperlukan, cukup polling antrian dengan memanggil take ().
Singkatnya: "sinkronisasi memori" terjadi secara implisit ketika Anda memulai utas, utas berakhir, Anda membaca variabel volatil, Anda membuka kunci monitor (meninggalkan blok / fungsi yang disinkronkan) dll. "Sinkronisasi" ini mempengaruhi (dalam arti "siram" ") semua penulisan dilakukan sebelum tindakan tertentu. Dalam kasus ConcurrentLinkedDeque yang disebutkan di atas , dokumentasi "mengatakan":
Perilaku implisit ini adalah aspek yang agak merusak karena kebanyakan programmer Java tanpa banyak pengalaman hanya akan mengambil banyak seperti yang diberikan karena itu. Dan kemudian tiba-tiba tersandung thread ini setelah Jawa tidak melakukan apa yang "seharusnya" dilakukan dalam produksi di mana ada beban kerja yang berbeda - dan itu cukup sulit untuk menguji masalah konkurensi.
sumber
Disinkronkan secara sederhana berarti bahwa beberapa utas jika dikaitkan dengan objek tunggal dapat mencegah baca dan tulis kotor jika blok yang disinkronkan digunakan pada objek tertentu. Untuk memberi Anda lebih banyak kejelasan, mari kita ambil contoh:
Kami telah membuat dua objek kelas MyRunnable, runnable1 dibagikan dengan utas 1 dan utas 3 & runnable2 dibagikan hanya dengan utas 2. Sekarang ketika t1 dan t3 dimulai tanpa disinkronkan sedang digunakan, output PFB yang menunjukkan bahwa kedua thread 1 dan 3 secara bersamaan mempengaruhi nilai var di mana untuk thread 2, var memiliki memori sendiri.
Menggunakan Sinkronisasi, utas 3 menunggu utas 1 selesai di semua skenario. Ada dua kunci yang diperoleh, satu di runnable1 dibagikan dengan utas 1 dan utas 3 dan lainnya pada runnable2 hanya dibagikan oleh utas 2.
sumber
disinkronkan sederhana berarti tidak ada dua utas yang dapat mengakses blok / metode secara bersamaan. Ketika kita mengatakan blok / metode kelas mana pun disinkronkan itu berarti hanya satu utas yang dapat mengaksesnya sekaligus. Secara internal utas yang mencoba mengaksesnya pertama-tama mengambil kunci pada objek itu dan selama kunci ini tidak tersedia, tidak ada utas lain yang dapat mengakses metode / blok yang disinkronkan dari instance kelas tersebut.
Catatan utas lainnya dapat mengakses metode objek yang sama yang tidak ditentukan untuk disinkronkan. Utas dapat melepaskan kunci dengan menelepon
sumber
synchronized
block in Java adalah monitor dalam multithreading.synchronized
blok dengan objek / kelas yang sama dapat dieksekusi oleh hanya satu utas, semua yang lain sedang menunggu. Ini dapat membanturace condition
situasi ketika beberapa utas mencoba memperbarui variabel yang sama (langkah pertama menggunakanvolatile
Tentang )Java 5
diperpanjangsynchronized
dengan mendukunghappens-before
[Tentang]Langkah selanjutnya adalah
java.util.concurrent
volatile vs disinkronkan
sumber
disinkronkan adalah kata kunci di Jawa yang digunakan untuk membuat hubungan sebelum terjadi di lingkungan multithreading untuk menghindari inkonsistensi memori dan kesalahan interferensi thread.
sumber