Saya pernah mendengar kata-kata ini yang berhubungan dengan pemrograman bersamaan, tetapi apa perbedaan di antara mereka?
concurrency
locking
mutex
semaphore
pemenang
sumber
sumber
Jawaban:
Kunci hanya memungkinkan satu utas untuk memasuki bagian yang dikunci dan kunci tidak dibagi dengan proses lain.
Mutex sama dengan kunci tetapi bisa lebar sistem (dibagi oleh beberapa proses).
Sebuah semaphore melakukan hal yang sama seperti mutex tetapi memungkinkan x jumlah benang untuk masuk, ini dapat digunakan misalnya untuk membatasi jumlah cpu, io atau ram tugas-tugas intensif berjalan pada waktu yang sama.
Untuk posting yang lebih detail tentang perbedaan antara mutex dan semaphore baca di sini .
Anda juga memiliki kunci baca / tulis yang memungkinkan pembaca tanpa batas atau 1 penulis pada waktu tertentu.
sumber
Ada banyak kesalahpahaman tentang kata-kata ini.
Ini dari pos sebelumnya ( https://stackoverflow.com/a/24582076/3163691 ) yang sangat cocok di sini:
1) Bagian Kritis = Objek pengguna yang digunakan untuk memungkinkan pelaksanaan hanya satu utas aktif dari banyak lainnya dalam satu proses . Utas yang tidak dipilih lainnya (@ mendapatkan objek ini) dimatikan .
[Tidak ada kemampuan proses, objek yang sangat primitif].
2) Mutex Semaphore (alias Mutex) = Objek kernel yang digunakan untuk memungkinkan eksekusi hanya satu utas aktif dari banyak lainnya, di antara proses yang berbeda . Utas yang tidak dipilih lainnya (@ mendapatkan objek ini) dimatikan . Objek ini mendukung kepemilikan utas, pemberitahuan penghentian utas, rekursi (beberapa panggilan 'dapatkan' dari utas yang sama) dan 'penghindaran inversi prioritas'.
[Kemampuan interprocess, sangat aman digunakan, semacam objek sinkronisasi 'tingkat tinggi'].
3) Menghitung Semaphore (alias Semaphore) = Objek kernel yang digunakan untuk memungkinkan eksekusi sekelompok utas aktif dari banyak lainnya. Utas yang tidak dipilih lainnya (@ mendapatkan objek ini) dimatikan .
[Namun kemampuan interproses tidak terlalu aman untuk digunakan karena tidak memiliki atribut 'mutex' berikut: pemberitahuan penghentian utas, rekursi ?, 'penghindaran inversi prioritas'?, Dll].
4) Dan sekarang, berbicara tentang 'spinlocks', pertama beberapa definisi:
Wilayah Kritis = Wilayah memori yang digunakan bersama oleh 2 proses atau lebih.
Kunci = Variabel yang nilainya memungkinkan atau menolak pintu masuk ke 'wilayah kritis'. (Ini bisa diimplementasikan sebagai 'bendera boolean' yang sederhana).
Busy waiting = Pengujian variabel secara berkesinambungan hingga beberapa nilai muncul.
Akhirnya:
Spin-lock (alias Spinlock) = Kunci yang menggunakan menunggu sibuk . (Pengambilan kunci dilakukan oleh xchg atau operasi atom serupa ).
[Tanpa thread thread, kebanyakan digunakan hanya pada level kernel. Tidak efisien untuk kode level Pengguna].
Sebagai komentar terakhir, saya tidak yakin tetapi saya dapat bertaruh Anda banyak uang bahwa 3 objek sinkronisasi pertama di atas (# 1, # 2 dan # 3) menggunakan binatang sederhana ini (# 4) sebagai bagian dari implementasinya.
Semoga harimu menyenangkan!.
Referensi:
-Real-Time Konsep untuk Sistem Tertanam oleh Qing Li dengan Caroline Yao (CMP Books).
-Sistem Operasi Modern (3) oleh Andrew Tanenbaum (Pearson Education International).
-Pemrograman Aplikasi untuk Microsoft Windows (4) oleh Jeffrey Richter (Microsoft Programming Series).
Anda juga dapat melihat: https://stackoverflow.com/a/24586803/3163691
sumber
Sebagian besar masalah dapat diselesaikan dengan menggunakan (i) hanya mengunci, (ii) hanya semafor, ..., atau (iii) kombinasi keduanya! Seperti yang mungkin Anda temukan, keduanya sangat mirip: keduanya mencegah kondisi balapan , keduanya memiliki
acquire()
/release()
operasi, keduanya menyebabkan nol atau lebih utas menjadi tersumbat / dicurigai ... Sungguh, perbedaan yang krusial hanya terletak pada bagaimana mereka mengunci dan membuka kunci .Untuk kedua kunci / semafor, mencoba menelepon
acquire()
saat primitif dalam keadaan 0 menyebabkan utas penangguhan ditangguhkan. Untuk kunci - upaya untuk mendapatkan kunci dalam keadaan 1 berhasil. Untuk semafor - upaya untuk mendapatkan kunci di status {1, 2, 3, ...} berhasil.Untuk kunci dalam keadaan 0, jika utas yang sama yang sebelumnya disebut
acquire()
, sekarang panggilan rilis, maka rilis berhasil. Jika utas yang berbeda mencoba ini - ini tergantung pada implementasi / pustaka tentang apa yang terjadi (biasanya upaya diabaikan atau kesalahan dilemparkan). Untuk semafor dalam status 0, utas apa pun dapat memanggil rilis dan itu akan berhasil (terlepas dari utas mana yang sebelumnya digunakan untuk meletakkan semafor dalam status 0).Dari diskusi sebelumnya, kita dapat melihat bahwa kunci memiliki gagasan tentang pemilik (utas satu-satunya yang dapat memanggil pelepasan adalah pemilik), sedangkan semafor tidak memiliki pemilik (utas apa pun dapat menyebut pelepasan pada semafor).
Apa yang menyebabkan banyak kebingungan adalah bahwa, dalam praktiknya ada banyak variasi definisi tingkat tinggi ini.
Variasi penting untuk dipertimbangkan :
acquire()
/release()
disebut? - [Bervariasi secara masif ]Ini tergantung pada buku / dosen / bahasa / perpustakaan / lingkungan Anda.
Berikut ini adalah tur singkat yang mencatat bagaimana beberapa bahasa menjawab detail ini.
C, C ++ ( pthreads )
pthread_mutex_t
. Secara default, mereka tidak dapat dibagi dengan proses lain (PTHREAD_PROCESS_PRIVATE
), namun mutex's memiliki atribut yang disebut berbagi . Saat disetel, maka mutex dibagi di antara proses (PTHREAD_PROCESS_SHARED
).sem_t
. Mirip dengan mutex, semaphore dapat dibagi antara tiga proses banyak atau dirahasiakan dengan utas dari satu proses tunggal. Ini tergantung pada argumen berbagi yang disediakan untuksem_init
.python ( threading.py )
threading.RLock
) sebagian besar sama dengan C / C ++pthread_mutex_t
s. Keduanya sama-sama reentrant . Ini berarti mereka hanya dapat dibuka oleh utas yang sama yang menguncinya. Ini adalah kasus bahwasem_t
semaphore,threading.Semaphore
semaphores dantheading.Lock
kunci tidak reentrant - karena itu adalah setiap thread dapat melakukan membuka kunci kunci / turun semaphore.threading.Semaphore
) sebagian besar sama dengansem_t
. Meskipun dengansem_t
, antrian id benang digunakan untuk mengingat urutan di mana utas menjadi diblokir ketika mencoba untuk menguncinya saat dikunci. Ketika utas membuka semafor, utas pertama dalam antrian (jika ada) dipilih untuk menjadi pemilik baru. Pengenal utas dihapus dari antrian dan semafor menjadi terkunci lagi. Namun, denganthreading.Semaphore
, set digunakan sebagai ganti antrian, sehingga urutan di mana utas menjadi diblokir tidak disimpan - utas apa pun dalam set dapat dipilih untuk menjadi pemilik berikutnya.Java ( java.util.concurrent )
java.util.concurrent.ReentrantLock
) sebagian besar sama dengan C / C ++pthread_mutex_t
's, dan Pythonthreading.RLock
dalam hal itu juga menerapkan kunci reentrant. Berbagi kunci antar proses lebih sulit di Jawa karena JVM bertindak sebagai perantara. Jika utas mencoba membuka kunci kunci yang bukan miliknya, sebuahIllegalMonitorStateException
dilemparkan.java.util.concurrent.Semaphore
) sebagian besar sama dengansem_t
danthreading.Semaphore
. Konstruktor untuk Java semaphores menerima parameter fairness boolean yang mengontrol apakah akan menggunakan set (false) atau antrian (true) untuk menyimpan utas menunggu.Secara teori, semaphore sering dibahas, tetapi dalam praktiknya, semaphores tidak banyak digunakan. Semafor hanya menyimpan status satu bilangan bulat, sehingga seringkali agak tidak fleksibel dan banyak yang diperlukan sekaligus - menyebabkan kesulitan dalam memahami kode. Juga, fakta bahwa utas apa pun dapat melepaskan semaphore terkadang tidak diinginkan. Lebih banyak primitif / abstraksi sinkronisasi berorientasi objek / tingkat tinggi seperti "variabel kondisi" dan "monitor" yang digunakan.
sumber
Lihatlah Tutorial Multithreading oleh John Kopplin.
Di bagian Sinkronisasi Antar Utas , ia menjelaskan perbedaan antara acara, kunci, mutex, semaphore, penghitung waktu tunggu
sumber
Saya akan mencoba menutupinya dengan contoh:
Kunci: Salah satu contoh di mana Anda akan menggunakan
lock
kamus yang dibagikan di mana item (yang harus memiliki kunci unik) ditambahkan.Kunci akan memastikan bahwa satu utas tidak memasukkan mekanisme kode yang memeriksa item dalam kamus, sedangkan utas lainnya (yang ada di bagian kritis) telah melewati pemeriksaan ini dan menambahkan item. Jika utas lain mencoba memasukkan kode yang dikunci, ia akan menunggu (diblokir) hingga objek dilepaskan.
Semaphore: Katakanlah Anda memiliki kumpulan koneksi, maka utas tunggal mungkin mencadangkan satu elemen di kumpulan dengan menunggu semaphore untuk mendapatkan koneksi. Kemudian menggunakan koneksi dan ketika pekerjaan selesai melepaskan koneksi dengan merilis semaphore.
Contoh kode yang saya sukai adalah salah satu bouncer yang diberikan oleh @Patric - begini:
Mutex Ini cukup banyak
Semaphore(1,1)
dan sering digunakan secara global (lebar aplikasi kalau tidak bisa dibilanglock
lebih tepat). Seseorang akan menggunakan globalMutex
ketika menghapus node dari daftar yang dapat diakses secara global (hal terakhir yang Anda ingin utas lainnya melakukan sesuatu saat Anda menghapus node). Ketika Anda memperolehMutex
jika utas yang berbeda mencoba mengakuisisi yang sama,Mutex
ia akan ditidurkan hingga utas SAMA yang memperolehMutex
pelepasannya.Contoh yang bagus untuk membuat mutex global adalah oleh @deepee
kemudian gunakan seperti:
Semoga ini menghemat waktu Anda.
sumber
Wikipedia memiliki bagian yang bagus tentang perbedaan antara Semaphores dan Mutex :
sumber
Pemahaman saya adalah bahwa mutex hanya untuk digunakan dalam satu proses tunggal, tetapi di banyak utasnya, sedangkan semafor dapat digunakan di berbagai proses, dan di seluruh rangkaian utasnya.
Juga, mutex adalah biner (baik terkunci atau tidak terkunci), sedangkan semaphore memiliki gagasan tentang penghitungan, atau antrian lebih dari satu permintaan kunci dan membuka kunci.
Bisakah seseorang memverifikasi penjelasan saya? Saya berbicara dalam konteks Linux, khususnya Red Hat Enterprise Linux (RHEL) versi 6, yang menggunakan kernel 2.6.32.
sumber
Menggunakan pemrograman C pada varian Linux sebagai contoh dasar untuk contoh.
Mengunci:
• Biasanya biner konstruksi yang sangat sederhana dalam operasi terkunci atau tidak terkunci
• Tidak ada konsep kepemilikan utas, prioritas, pengurutan dll.
• Biasanya kunci putaran di mana utas terus-menerus memeriksa ketersediaan kunci.
• Biasanya bergantung pada operasi atom misalnya Uji-dan-set, bandingkan-dan-tukar, ambil-dan-tambah dll.
• Biasanya memerlukan dukungan perangkat keras untuk operasi atom.
File Locks:
• Biasanya digunakan untuk mengoordinasikan akses ke file melalui berbagai proses.
• Beberapa proses dapat menahan kunci baca namun ketika proses tunggal menahan kunci tulis tidak ada proses lain yang diizinkan untuk mendapatkan kunci baca atau tulis.
• Contoh: kawanan, fcntl dll.
Mutex:
• Panggilan fungsi mutex biasanya bekerja di ruang kernel dan menghasilkan panggilan sistem.
• Menggunakan konsep kepemilikan. Hanya utas yang saat ini memegang mutex yang dapat membukanya.
• Mutex tidak bersifat rekursif (Pengecualian: PTHREAD_MUTEX_RECURSIVE).
• Biasanya digunakan dalam Asosiasi dengan Variabel Kondisi dan diteruskan sebagai argumen untuk misalnya pthread_cond_signal, pthread_cond_wait dll.
• Beberapa sistem UNIX memungkinkan mutex untuk digunakan oleh beberapa proses meskipun ini mungkin tidak diberlakukan pada semua sistem.
Tiang sinyal:
• Ini adalah integer yang dikelola kernel yang nilainya tidak diperbolehkan turun di bawah nol.
• Dapat digunakan untuk menyinkronkan proses.
• Nilai semaphore dapat diatur ke nilai yang lebih besar dari 1 dalam hal nilai biasanya menunjukkan jumlah sumber daya yang tersedia.
• Semafor yang nilainya terbatas pada 1 dan 0 disebut sebagai semaphore biner.
sumber
Supporting ownership
,maximum number of processes share lock
danmaximum number of allowed processes/threads in critical section
tiga faktor utama yang menentukan nama / jenis objek bersamaan dengan nama umumlock
. Karena nilai dari faktor-faktor ini adalah biner (memiliki dua status), kita dapat meringkasnya dalam tabel 3 * 8 seperti kebenaran.Merasa bebas untuk mengedit atau memperluas tabel ini, saya telah mempostingnya sebagai tabel ascii untuk dapat diedit :)
sumber