Konkurensi multi-thread dapat dicapai di JAVA melalui pernyataan tersinkronisasi. Menggunakan blok kode yang disinkronkan, JVM memastikan bahwa hanya satu thread yang dapat mengunci objek tertentu pada saat yang bersamaan. Mekanisme kunci memungkinkan banyak thread mengakses sumber daya penting dengan aman.
Kode sinkronisasi ditulis sebagai berikut:
Kode 1:
Objek obj = objek baru(); ... tersinkronisasi(obj) {//TODO: Akses sumber daya penting} Multi-threading JAVA selalu penuh dengan jebakan. Jika kita menggunakan Boolean sebagai objek tersinkronisasi, dua situasi berikut mungkin terjadi:
1. Diperkirakan satu objek terkunci, namun objek yang berbeda sebenarnya tersinkronisasi.
Kode 2:
private volatil Boolean isTrue = false; publich void aMethod() { ... disinkronkan(isTrue) { isTrue = !isTrue; //TODO: Akses sumber daya penting isTrue = !isTrue; Sekilas, tidak ada yang salah dengan kode di atas. Karena penggunaan tersinkronisasi (isTrue), hanya satu thread yang dapat mengakses sumber daya penting secara bersamaan, namun tidak demikian. Karena dua konstanta false dan true berhubungan dengan dua objek yang berbeda. Ketika isTrue berubah, kemungkinan thread yang berbeda akan menyinkronkan objek yang berbeda. Tinju otomatis JAVA akan mengubah false menjadi Boolean.FALSE dan true menjadi Boolean.TRUE (ini juga menunjukkan bahwa jika false diubah menjadi Boolean.FALSE, hasilnya akan sama). Tulis kode pengujian untuk salah satu situasi di atas sebagai berikut:
Kode 3:
public class BooleanTest { private volatil Boolean isTrue = Boolean.FALSE; //Sama dengan false di sini public void aMethod() { for(int i=0;i<10;i++) { Thread t = new Thread() { public void run() { disinkronkan(isTrue) { isTrue = !isTrue; System.out.println(Thread.currentThread().getName() + " - isTrue=" + isTrue); coba{ Lari ganda = 1000 * Math.random(); Thread.sleep(ran.intValue()); }catch(InterruptedException e) {} if(!isTrue) System.out.println( Thread.currentThread().getName() + " - Oh, Tidak!"); isTrue = !isTrue(); t.start(); } } public static void main(String... args) { Uji Boolean bt = Uji Boolean baru(); Saat Anda menjalankan kode di atas, Anda akan melihat "-Oh, Tidak!", yang menunjukkan bahwa thread yang berbeda memasuki blok kode yang disinkronkan secara bersamaan.
2. Dikira objek-objek yang berbeda disinkronkan, padahal sebenarnya itu adalah satu objek.
Terkadang kita mungkin ingin melakukan sinkronisasi pada beberapa objek. Jika Boolean digunakan sebagai objek yang disinkronkan, kemungkinan besar dua blok sinkronisasi yang seharusnya tidak memiliki hubungan menggunakan kunci objek yang sama. Contohnya adalah sebagai berikut:
Kode 4:
private volatil Boolean aBoolean = Boolean.FALSE; private volatil Boolean anotherBoolean = false; public void aMethod() { ... disinkronkan(aBoolean) { //TODO: Akses sumber daya penting 1 } ... } public void anotherMethod() { . .. disinkronkan(AnotherBoolean) { //TODO: Akses sumber daya penting 2 } ... } Asumsikan bahwa awalnya aMethod dan anotherMethod akan dipanggil oleh dua set thread yang tidak berhubungan. Namun, karena Boolean.FALSE dan false menunjuk ke objek yang sama, akses ke sumber daya penting 2 mungkin diblokir oleh sumber daya penting 1 (dan sebaliknya).
Dua situasi di atas menunjukkan bahwa saat menggunakan blok yang disinkronkan, cobalah untuk tidak menggunakan objek Boolean sebagai objek yang disinkronkan, jika tidak, masalah yang tidak terduga dapat terjadi, atau jebakan dapat terjadi pada modifikasi kode di masa mendatang.
Dari sini juga terlihat bahwa sinkronisasi konstanta apa pun berisiko. Jika Anda harus menyinkronkan Boolean, Anda harus menggunakan operator baru untuk membuat objek Boolean.