Copy kode kodenya sebagai berikut:
run void tersinkronisasi publik()
{
}
Seperti dapat dilihat dari kode di atas, selama kata kunci sinkronisasi ditambahkan antara void dan public, metode run dapat disinkronkan. Artinya, untuk instance objek dari kelas Java yang sama, metode run hanya dapat disinkronkan dipanggil oleh satu thread pada saat yang sama, dan dapat dipanggil oleh thread lain hanya setelah eksekusi saat ini. Meskipun thread saat ini mengeksekusi metode hasil dalam metode run, thread tersebut hanya berhenti sebentar. Karena thread lain tidak dapat menjalankan metode run, thread saat ini pada akhirnya akan melanjutkan eksekusi. Perhatikan kode berikut terlebih dahulu:
Kata kunci yang disinkronkan hanya terikat pada satu contoh objek
Copy kode kodenya sebagai berikut:
Tes kelas
{
metode kekosongan tersinkronisasi publik()
{
}
}
Sinkronisasi kelas publik mengimplementasikan Runnable
{
tes Tes pribadi;
menjalankan kekosongan publik()
{
tes.metode();
}
Sinkronisasi publik (Uji uji)
{
this.tes = tes;
}
public static void main(String[] args) memunculkan Pengecualian
{
Tes tes1 = Tes baru();
Tes tes2 = Tes baru();
Sinkronisasi sinkronisasi1 = Sinkronisasi baru(uji1);
Sinkronisasi sinkronisasi2 = Sinkronisasi baru(uji2);
Utas baru(sinkronisasi1).mulai();
Utas baru(sinkronisasi2).mulai();
}
}
Metode metode di kelas Test bersifat sinkron. Namun kode di atas membuat dua instance kelas Test, sehingga metode metode test1 dan test2 dijalankan secara terpisah. Untuk menyinkronkan metode, Anda harus meneruskan instance kelas Test yang sama ke konstruktornya saat membuat instance kelas Sync, seperti yang ditunjukkan dalam kode berikut:
Sinkronisasi sinkronisasi1 = Sinkronisasi baru(uji1);
Anda tidak hanya dapat menggunakan sinkronisasi untuk menyinkronkan metode non-statis, Anda juga dapat menggunakan sinkronisasi untuk menyinkronkan metode statis. Misalnya, metode metode dapat didefinisikan sebagai berikut:
Copy kode kodenya sebagai berikut:
Tes kelas
{
metode kekosongan tersinkronisasi statis publik() {}
}
Buat instance objek dari kelas Test sebagai berikut:
Tes tes = Tes baru();
Untuk metode statis, selama kata kunci tersinkronisasi ditambahkan, metode tersebut disinkronkan. Baik Anda menggunakan test.method() atau Test.method() untuk memanggil metode metode, metode tersebut disinkronkan dan tidak ada masalah dengan banyak contoh metode non-statis.
Di antara 23 pola desain, mode Singleton juga tidak aman untuk thread jika dirancang menurut metode tradisional.
Copy kode kodenya sebagai berikut:
tes paket;
// Mode Singleton yang aman untuk thread
kelas Singleton
{
sampel Singleton statis pribadi;
pribadi Singleton()
{
}
getInstance Singleton statis publik()
{
jika (sampel == nol)
{
Thread.yield(); // Untuk memperkuat ketidakamanan thread pada mode Singleton
sampel = Singleton baru();
}
sampel kembali;
}
}
kelas publik MyThread memperluas Thread
{
menjalankan kekosongan publik()
{
Singleton singleton = Singleton.getInstance();
Sistem.keluar.println(singleton.hashCode());
}
public static void main(String[] args)
{
Utas utas[] = Utas baru[5];
for (int i = 0; i < benang.panjang; i++)
thread[i] = new MyThread();
for (int i = 0; i < benang.panjang; i++)
benang[i].mulai();
}
}
Metode hasil dipanggil dalam kode di atas untuk memunculkan ketidakamanan thread dalam mode tunggal. Jika baris ini dihilangkan, implementasi di atas masih merupakan thread tidak aman, tetapi kemungkinan terjadinya jauh lebih kecil.
Hasil dari menjalankan program adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
25358555
26399554
7051261
29855319
5383406
Hasil pengoperasian di atas mungkin berbeda di lingkungan pengoperasian yang berbeda, namun secara umum keluaran kelima baris tidak akan sama persis. Seperti yang bisa dilihat dari keluaran ini, ada lima contoh objek yang diperoleh melalui metode getInstance, bukan satu seperti yang kita harapkan. Hal ini karena ketika sebuah thread mengeksekusi Thread.yield(), ia menyerahkan sumber daya CPU ke thread lain. Karena pernyataan untuk membuat instance objek Singleton tidak dijalankan saat berpindah antar thread, semua thread ini meneruskan penilaian if, sehingga lima instance objek akan dibuat (empat dapat dibuat). penilaian if sebelum membuat objek Singleton, hasilnya mungkin berbeda setiap kali dijalankan).
Untuk membuat mode singleton di atas aman untuk thread, cukup tambahkan kata kunci tersinkronisasi ke getInstance. Kodenya adalah sebagai berikut:
Singleton getInstance() tersinkronisasi statis publik() {}
Tentunya ada cara yang lebih sederhana yaitu dengan membuat objek Singleton saat mendefinisikan variabel Singleton. Kodenya adalah sebagai berikut:
sampel Singleton final statis pribadi = new Singleton();
Kemudian kembalikan saja sampelnya langsung dalam metode getInstance. Meskipun metode ini sederhana, namun tidak fleksibel dalam membuat objek Singleton dalam metode getInstance. Pembaca dapat memilih untuk menggunakan metode berbeda untuk menerapkan pola tunggal sesuai dengan kebutuhan spesifik.
Ada empat hal yang perlu diperhatikan saat menggunakan kata kunci tersinkronisasi:
1. Kata kunci tersinkronisasi tidak dapat diwariskan.
Meskipun Anda dapat menggunakan sinkronisasi untuk mendefinisikan metode, sinkronisasi bukan bagian dari definisi metode, sehingga kata kunci sinkronisasi tidak dapat diwarisi. Jika metode di kelas induk menggunakan kata kunci tersinkronisasi dan metode tersebut diganti di subkelas, metode di subkelas tidak disinkronkan secara default dan harus ditentukan secara eksplisit di subkelas. Cukup tambahkan kata kunci tersinkronisasi ke metode tersebut. Tentu saja, Anda juga dapat memanggil metode yang sesuai di kelas induk dalam metode subkelas. Dengan cara ini, meskipun metode dalam subkelas tidak sinkron, subkelas memanggil metode sinkronisasi dari kelas induk subkelas setara dengan sinkronisasi. Contoh kode untuk kedua metode ini adalah sebagai berikut:
Tambahkan kata kunci tersinkronisasi ke metode subkelas
Copy kode kodenya sebagai berikut:
kelas Orangtua
{
metode kekosongan tersinkronisasi publik() {} }
}
kelas Anak memperluas Induk
{
metode kekosongan tersinkronisasi publik() {} }
}
Panggil metode tersinkronisasi dari kelas induk dalam metode subkelas
Copy kode kodenya sebagai berikut:
kelas Orangtua
{
metode kekosongan tersinkronisasi publik() {} }
}
kelas Anak memperluas Induk
{
metode kekosongan publik() { super.metode();
}
2. Kata kunci tersinkronisasi tidak dapat digunakan saat mendefinisikan metode antarmuka.
3. Konstruktor tidak dapat menggunakan kata kunci tersinkronisasi, tetapi dapat menggunakan blok tersinkronisasi yang akan dibahas di bagian selanjutnya untuk sinkronisasi.
4. disinkronkan dapat ditempatkan secara bebas.
Pada contoh sebelumnya, kata kunci sinkronisasi ditempatkan di depan tipe pengembalian metode. Tapi ini bukan satu-satunya tempat yang bisa disinkronkan. Pada metode non-statis, sinkronisasi juga dapat ditempatkan di depan definisi metode. Pada metode statis, sinkronisasi dapat ditempatkan di depan statis.
Copy kode kodenya sebagai berikut:
metode void tersinkronisasi publik();
metode kekosongan publik yang disinkronkan();
metode void tersinkronisasi statis publik();
metode void statis tersinkronisasi publik();
metode void statis publik yang disinkronkan();
Namun perlu diingat bahwa sinkronisasi tidak dapat ditempatkan setelah tipe pengembalian metode. Misalnya, kode berikut salah:
Copy kode kodenya sebagai berikut:
metode sinkronisasi public void();
metode sinkronisasi public static void();
Kata kunci tersinkronisasi hanya dapat digunakan untuk menyinkronkan metode, bukan variabel kelas. Kode berikut juga salah.
Copy kode kodenya sebagai berikut:
int tersinkronisasi publik n = 0;
int tersinkronisasi statis publik n = 0;
Meskipun menggunakan metode sinkronisasi kata kunci yang disinkronkan adalah metode sinkronisasi yang paling aman, penggunaan kata kunci yang disinkronkan secara ekstensif akan menyebabkan konsumsi sumber daya yang tidak perlu dan hilangnya kinerja. Meskipun di permukaan tampaknya sinkronisasi mengunci suatu metode, pada kenyataannya sinkronisasi mengunci sebuah kelas. Dengan kata lain, jika sinkronisasi digunakan saat mendefinisikan metode non-statis metode1 dan metode2, metode2 tidak dapat dijalankan sebelum metode1 dijalankan. Situasi serupa terjadi pada metode statis dan non-statis. Namun metode statis dan non-statis tidak saling mempengaruhi. Lihatlah kode berikut:
Copy kode kodenya sebagai berikut:
tes paket;
kelas publik MyThread1 memperluas Thread
{
Nama metode String publik;
metode kekosongan statis publik (String s)
{
Sistem.keluar.println;
sementara (benar)
}
metode kekosongan tersinkronisasi publik1()
{
metode("metode1 metode non-statis");
}
metode kekosongan tersinkronisasi publik2()
{
metode("metode2 metode non-statis");
}
metode kekosongan tersinkronisasi statis publik3()
{
metode("metode statis3 metode");
}
metode kekosongan tersinkronisasi statis publik4()
{
metode("metode statis4 metode");
}
menjalankan kekosongan publik()
{
mencoba
{
getClass().getMethod(methodName).invoke(ini);
}
tangkapan (Pengecualian e)
{
}
}
public static void main(String[] args) memunculkan Pengecualian
{
MyThread1 myThread1 = baru MyThread1();
untuk (int saya = 1; saya <= 4; saya++)
{
myThread1.methodName = "metode" + String.valueOf(i);
Utas baru(Utasku1).mulai();
tidur(100);
}
}
}
Hasil yang berjalan adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Metode non-statis1 metode
Metode statis3 metode
Terlihat dari hasil running di atas bahwa metode2 dan metode4 tidak dapat dijalankan sebelum metode1 dan metode3 selesai. Oleh karena itu, kita dapat menarik kesimpulan bahwa jika Anda menggunakan kata kunci tersinkronisasi untuk mendefinisikan metode non-statis di suatu kelas, itu akan memengaruhi semua metode non-statis yang ditentukan menggunakan kata kunci tersinkronisasi di kelas ini. Jika metode statis didefinisikan, itu akan mempengaruhi semua metode statis yang ditentukan menggunakan kata kunci tersinkronisasi di kelas. Ini seperti kunci tabel dalam tabel data. Ketika catatan diubah, sistem mengunci seluruh tabel. Oleh karena itu, penggunaan metode sinkronisasi ini secara ekstensif akan mengurangi kinerja program secara signifikan.