Apa arti "atom" dalam pemrograman?

276

Dalam buku Java Efektif, ia menyatakan:

Spesifikasi bahasa menjamin bahwa membaca atau menulis variabel adalah atom kecuali variabelnya bertipe longatau double[JLS, 17.4.7].

Apa arti "atomik" dalam konteks pemrograman Java, atau pemrograman secara umum?

James
sumber
24
Satu operasi dalam satu waktu.
Subhrajyoti Majumder
1
hanya satu operasi yang dapat dilakukan pada variabel pada satu waktu.
kaysush
1
Saya curiga pertanyaan filsafat termasuk dalam codereview.stackexchange.com
Phlip
Memperhatikan bahwa beberapa variabel tidak secara default memiliki atomic read and write, menyatakannya sebagai volatile longatau volatile doublemembuat atomic read dan write atomic.
H2ONaCl

Jawaban:

372

Ini sebuah contoh, karena sebuah contoh seringkali lebih jelas daripada penjelasan yang panjang. Misalkan fooadalah variabel tipe long. Operasi berikut bukan operasi atom:

foo = 65465498L;

Memang, variabel ditulis menggunakan dua operasi terpisah: satu yang menulis 32 bit pertama, dan yang kedua yang menulis 32 bit terakhir. Itu berarti bahwa utas lain mungkin membaca nilai foo, dan melihat kondisi perantara.

Membuat operasi atom terdiri dari penggunaan mekanisme sinkronisasi untuk memastikan bahwa operasi terlihat, dari utas lainnya, sebagai atom tunggal (yaitu tidak dapat dibelah-belah), operasi. Itu berarti bahwa utas lainnya, setelah operasi dibuat atom, akan melihat nilai foosebelum penugasan, atau setelah penugasan. Tetapi tidak pernah nilai tengahnya.

Cara sederhana untuk melakukan ini adalah membuat variabel mudah berubah :

private volatile long foo;

Atau untuk menyinkronkan setiap akses ke variabel:

public synchronized void setFoo(long value) {
    this.foo = value;
}

public synchronized long getFoo() {
    return this.foo;
}
// no other use of foo outside of these two methods, unless also synchronized

Atau untuk menggantinya dengan AtomicLong:

private AtomicLong foo;
JB Nizet
sumber
75
Jadi ini dengan asumsi bahwa itu berjalan dalam sistem 32-bit. Bagaimana jika itu sistem 64 bit? Will foo = 65465498L; menjadi atom itu?
Harke
46
@ Marke Jika Anda menjalankan Java 64 bit, ya.
Jeroen
4
Apakah ini juga berlaku untuk C # dan .NET? Jika ya, untuk mendapatkan perilaku atom, CLR harus 64-bit?
Fabiano
5
@ Fabiano Ini berlaku dan inilah cara mencapainya di .NET karena kami tidak memiliki kata kunci yang disinkronkan seperti Java. stackoverflow.com/questions/541194/…
The Muffin Man
2
Kemudian mari kita asumsikan thread A memberikan nilai lama kemudian di setengah jalan thread B mencoba membacanya. Jika operasi A adalah atom, maka utas B akan menunggu sampai selesai? Ini berarti operasi atom akan menyediakan keamanan thread-implisit?
Teoman shipahi
60

"Operasi atom" berarti operasi yang tampaknya seketika dari perspektif semua utas lainnya. Anda tidak perlu khawatir tentang operasi yang sebagian selesai ketika jaminan berlaku.

H2ONaCl
sumber
25

Ini adalah sesuatu yang "muncul ke seluruh sistem terjadi secara instan", dan jatuh di bawah kategorisasi Linearizability dalam proses komputasi. Mengutip artikel yang ditautkan lebih lanjut:

Atomicity adalah jaminan isolasi dari proses bersamaan. Selain itu, operasi atom umumnya memiliki definisi berhasil atau gagal - mereka baik berhasil mengubah keadaan sistem, atau tidak memiliki efek yang jelas.

Jadi, misalnya, dalam konteks sistem basis data, seseorang dapat memiliki 'komitmen atom', yang berarti bahwa Anda dapat mendorong perubahan set pemutakhiran ke basis data relasional dan perubahan-perubahan itu akan diserahkan, atau tidak ada sama sekali dalam jika terjadi kegagalan, dengan cara ini data tidak menjadi rusak, dan konsekuensi dari penguncian dan / atau antrian, operasi selanjutnya akan menjadi penulisan atau pembacaan yang berbeda, tetapi hanya setelah fakta. Dalam konteks variabel dan threading ini hampir sama, diterapkan pada memori.

Kutipan Anda menyoroti bahwa perilaku ini tidak diharapkan dalam semua kasus.

Grant Thomas
sumber
15

Baru saja menemukan posting Operasi Atom vs Non-Atom sangat membantu saya.

"Suatu operasi yang bekerja pada memori bersama adalah atom jika ia menyelesaikan dalam satu langkah relatif terhadap utas lainnya.

Ketika penyimpanan atom dilakukan pada memori bersama, tidak ada utas lain yang dapat mengamati modifikasi tersebut setengah-lengkap.

Ketika muatan atom dilakukan pada variabel yang dibagikan, itu membaca seluruh nilai seperti yang muncul pada satu saat waktu. "

Kurt Zhong
sumber
14

Jika Anda memiliki beberapa utas yang menjalankan metode m1 dan m2 dalam kode di bawah ini:

class SomeClass {
    private int i = 0;

    public void m1() { i = 5; }
    public int m2() { return i; }
}

Anda memiliki jaminan bahwa setiap panggilan thread m2akan membaca 0 atau 5.

Di sisi lain, dengan kode ini ( ipanjangnya):

class SomeClass {
    private long i = 0;

    public void m1() { i = 1234567890L; }
    public long m2() { return i; }
}

panggilan thread m2dapat membaca 0, 1234567890L, atau beberapa nilai acak lainnya karena pernyataan i = 1234567890Ltersebut tidak dijamin atom untuk long(JVM dapat menulis 32 bit pertama dan 32 bit terakhir dalam dua operasi dan sebuah thread dapat mengamati idi antaranya) .

assylias
sumber
mengapa Anda berpikir bahwa "panjang" menyebabkan masalah sementara "int" tidak? Silakan lihat di sini geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/…
onmyway133
1
@entropy panjang dan penugasan ganda tidak dijamin atom di Jawa. Jadi Anda bisa membaca lama di mana hanya setengah dari bit telah diperbarui mengikuti tugas.
assylias
0

Di Jawa membaca dan menulis bidang semua jenis kecuali panjang dan ganda terjadi secara atom, dan jika bidang tersebut dideklarasikan dengan pengubah volatil, bahkan panjang dan ganda dibaca dan ditulis secara atom. Artinya, kita mendapatkan 100% apa yang ada di sana, atau apa yang terjadi di sana, juga tidak ada hasil antara dalam variabel.

Eugene Shamkin
sumber