Jika saya memiliki kelas util dengan metode statis yang akan memanggil fungsi Hibernate untuk mencapai akses data dasar. Saya bertanya-tanya apakah membuat metode synchronized
ini merupakan pendekatan yang tepat untuk memastikan keamanan benang.
Saya ingin ini mencegah akses info ke instance DB yang sama. Namun, saya sekarang yakin jika kode berikut mencegah getObjectById
dipanggil untuk semua Kelas ketika dipanggil oleh kelas tertentu.
public class Utils {
public static synchronized Object getObjectById (Class objclass, Long id) {
// call hibernate class
Session session = new Configuration().configure().buildSessionFactory().openSession();
Object obj = session.load(objclass, id);
session.close();
return obj;
}
// other static methods
}
For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
Jadi jika satu thread memasuki sebuah metode statis, sama objek dikembalikan oleh Object # getClass terkunci. Utas lain masih dapat mengakses metode contoh.Class
objek, dibuat oleh salah satu classloader mesin virtual. Seperti semua objek, objek ini juga memilikiMonitor
keterkaitan dengannya. Dan monitor ini sedang dikunci.Untuk menjawab pertanyaan secara lebih umum ...
Perlu diingat bahwa menggunakan metode yang disinkronkan benar-benar hanya singkatan (anggap kelas adalah SomeClass):
sama dengan
dan
sama dengan
Anda dapat menggunakan objek apa pun sebagai kunci. Jika Anda ingin mengunci himpunan bagian dari metode statis, Anda bisa
(untuk metode non-statis, Anda ingin menjadikan kunci sebagai bidang non-statis)
sumber
Metode statis menggunakan kelas sebagai objek untuk mengunci, yaitu Utils.class untuk contoh Anda. Jadi ya, tidak apa-apa.
sumber
static synchronized
berarti memegang kunci pada objek kelas diClass
mana sebagaisynchronized
berarti memegang kunci pada objek kelas itu sendiri. Itu berarti, jika Anda mengakses metode tersinkronisasi non-statis di utas (eksekusi) Anda masih dapat mengakses metode tersinkronisasi statis menggunakan utas lain.Jadi, mengakses dua jenis metode yang sama (baik dua metode statis atau dua metode non-statis) pada suatu titik waktu oleh lebih dari utas tidak mungkin.
sumber
Mengapa Anda ingin menegakkan bahwa hanya satu utas yang dapat mengakses DB pada suatu waktu?
Merupakan tugas driver database untuk mengimplementasikan penguncian yang diperlukan, dengan asumsi a
Connection
hanya digunakan oleh satu utas pada satu waktu!Kemungkinan besar, basis data Anda mampu menangani beberapa akses paralel
sumber
Jika ada hubungannya dengan data dalam database Anda, mengapa tidak menggunakan penguncian isolasi database untuk mencapai?
sumber
Untuk menjawab pertanyaan Anda, ya itu:
synchronized
metode Anda tidak dapat dijalankan oleh lebih dari satu utas sekaligus.sumber
Bagaimana
synchronized
kerja kata kunci JavaKetika Anda menambahkan
synchronized
kata kunci ke metode statis, metode ini hanya dapat dipanggil dengan utas tunggal setiap kali.Dalam kasus Anda, setiap pemanggilan metode akan:
SessionFactory
Session
Namun, ini adalah persyaratan Anda:
getObjectById
dipanggil untuk semua kelas ketika dipanggil oleh kelas tertentuJadi, bahkan jika
getObjectById
metodenya aman, implementasinya salah.SessionFactory
praktik terbaikIni
SessionFactory
adalah thread-safe, dan ini adalah objek yang sangat mahal untuk dibuat karena perlu mengurai kelas entitas dan membangun representasi metamodel entitas internal.Jadi, Anda tidak harus membuat
SessionFactory
pada setiapgetObjectById
pemanggilan metode.Sebagai gantinya, Anda harus membuat contoh tunggal untuk itu.
The
Session
harus selalu tertutupAnda tidak menutup
Session
dalamfinally
blok, dan ini bisa membocorkan sumber daya basis data jika pengecualian dilemparkan saat memuat entitas.Menurut
Session.load
metode JavaDoc mungkin membuangHibernateException
jika entitas tidak dapat ditemukan dalam database.Itu sebabnya Anda perlu menggunakan
finally
blok untuk menutupSession
, seperti ini:Mencegah akses multi-utas
Dalam kasus Anda, Anda ingin memastikan hanya satu utas yang mendapatkan akses ke entitas tertentu.
Tetapi
synchronized
kata kunci hanya mencegah dua utas memanggilgetObjectById
secara bersamaan. Jika kedua utas memanggil metode ini satu demi satu, Anda masih akan memiliki dua utas menggunakan entitas ini.Jadi, jika Anda ingin mengunci objek database tertentu sehingga tidak ada utas lain yang dapat memodifikasinya, maka Anda perlu menggunakan kunci basis data.
Kata
synchronized
kunci hanya berfungsi dalam JVM tunggal. Jika Anda memiliki beberapa web node, ini tidak akan mencegah akses multi-thread di beberapa JVM.Yang perlu Anda lakukan adalah menggunakan
LockModeType.PESSIMISTIC_READ
atauLockModeType.PESSIMISTIC_WRITE
saat menerapkan perubahan pada DB, seperti ini:Jadi, inilah yang saya lakukan:
EntityTransaction
dan memulai transaksi basis data baruPost
entitas sambil memegang kunci pada catatan database terkaitPost
entitas dan melakukan transaksiException
pelemparan, saya memutar kembali transaksisumber