روش های موثر برای استفاده از قفل در کاتلین

Summarize this content to 400 words in Persian Lang
در Kotlin، قفل ها نقش مهمی در تضمین ایمنی نخ ایفا می کنند، زمانی که چندین رشته به منابع مشترک دسترسی دارند. در اینجا روش های اصطلاحی رایج برای استفاده از قفل در Kotlin آمده است:
1. استفاده از ReentrantLock با lock() و unlock()
صریح ترین راه برای استفاده از قفل در کاتلین تماس گرفتن است lock() و unlock() به صورت دستی این کنترل دقیقی را بر روی زمانی که قفل به دست می آید و آزاد می شود، فراهم می کند.
مثال:
import java.util.concurrent.locks.ReentrantLock
class SafeCounter {
private val lock = ReentrantLock()
private var count = 0
fun increment() {
lock.lock() // Explicitly acquire the lock
try {
count++
println(“Incremented to: $count”)
} finally {
lock.unlock() // Ensure the lock is released even if an exception occurs
}
}
fun getCount(): Int {
lock.lock()
return try {
count
} finally {
lock.unlock()
}
}
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println(“Final count: ${counter.getCount()}”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
2. استفاده از withLock تابع پسوند
را withLock تابع افزونه استفاده از قفل را در Kotlin با مدیریت آن ساده می کند lock() و unlock() به طور خودکار تماس می گیرد.
مثال:
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class SafeList {
private val lock = ReentrantLock()
private val list = mutableListOf<String>()
fun add(item: String) {
lock.withLock {
list.add(item)
}
}
fun getList(): List<String> {
lock.withLock {
return list.toList() // Return a copy for safety
}
}
}
fun main() {
val safeList = SafeList()
val threads = List(5) { index ->
Thread {
safeList.add(“Item-$index”)
}
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println(“Final list: ${safeList.getList()}”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
3. استفاده از synchronized
را synchronized کلمه کلیدی جایگزین ساده تری برای همگام سازی اولیه با قفل کردن روی یک شی مانیتور خاص ارائه می دهد.
مثال:
class SafeCounter {
private var count = 0
fun increment() {
synchronized(this) { // Synchronize on the instance itself
count++
println(“Incremented to: $count”)
}
}
fun getCount(): Int {
synchronized(this) {
return count
}
}
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println(“Final count: ${counter.getCount()}”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
4. استفاده از ReadWriteLock
برای سناریوهایی با خواندن مکرر و نوشتن نادر، ReadWriteLock قفل های جداگانه ای برای خواندن و نوشتن فراهم می کند که به چندین رشته اجازه می دهد همزمان بخوانند.
مثال:
import java.util.concurrent.locks.ReentrantReadWriteLock
class SafeMap {
private val lock = ReentrantReadWriteLock()
private val map = mutableMapOf<String, String>()
fun put(key: String, value: String) {
lock.writeLock().lock()
try {
map[key] = value
} finally {
lock.writeLock().unlock()
}
}
fun get(key: String): String? {
lock.readLock().lock()
return try {
map[key]
} finally {
lock.readLock().unlock()
}
}
}
fun main() {
val safeMap = SafeMap()
val threads = List(5) { index ->
Thread { safeMap.put(“Key-$index”, “Value-$index”) }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println(“Final map: $safeMap”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
5. استفاده از Coroutines و Mutex
برای همزمانی مبتنی بر کوروتین، کاتلین این را ارائه می دهد Mutex کلاس از kotlinx.coroutines.sync. این یک قفل معمولی است که از مسدود کردن نخ ها جلوگیری می کند.
مثال:
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class SafeCounter {
private val mutex = Mutex()
private var count = 0
suspend fun increment() {
mutex.withLock {
count++
println(“Incremented to: $count”)
}
}
fun getCount(): Int = count
}
fun main() = runBlocking {
val counter = SafeCounter()
val jobs = List(10) {
launch {
counter.increment()
}
}
jobs.forEach { it.join() }
println(“Final count: ${counter.getCount()}”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
6. استفاده از متغیرهای اتمی
برای سناریوهای ساده، متغیرهای اتمی مانند AtomicInteger و AtomicLong جایگزینی بدون قفل برای شمارنده ها و آکومولاتورهای ایمن با رزوه ارائه کنید.
مثال:
import java.util.concurrent.atomic.AtomicInteger
class SafeCounter {
private val count = AtomicInteger(0)
fun increment() {
println(“Incremented to: ${count.incrementAndGet()}”)
}
fun getCount(): Int = count.get()
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println(“Final count: ${counter.getCount()}”)
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
چه زمانی از هر کدام استفاده کنیم؟
ReentrantLock + lock/unlock: برای کنترل سطح پایین استفاده کنید، به خصوص زمانی که به ویژگی های پیشرفته مانند قفل های قطع شونده نیاز است.
withLock: رویکرد اصطلاحی کاتلین برای بیشتر موارد استفاده.
synchronized: ساده و سرراست برای همگام سازی اولیه.
ReadWriteLock: ایده آل برای خواندن مکرر و نوشتن نادر.
Mutex: بهترین برای همزمانی مبتنی بر کوروتین.
متغیرهای اتمی: سبک و بدون قفل، مناسب برای شمارنده و آکومولاتور.
هر رویکرد نیازهای خاصی را بر اساس پیچیدگی، عملکرد، و اینکه آیا شما با رشتهها یا کوروتینها کار میکنید، برآورده میکند. درک این گزینه ها تضمین می کند که می توانید برنامه های همزمان ایمن و کارآمد Kotlin را بنویسید.
در Kotlin، قفل ها نقش مهمی در تضمین ایمنی نخ ایفا می کنند، زمانی که چندین رشته به منابع مشترک دسترسی دارند. در اینجا روش های اصطلاحی رایج برای استفاده از قفل در Kotlin آمده است:
1. استفاده از ReentrantLock
با lock()
و unlock()
صریح ترین راه برای استفاده از قفل در کاتلین تماس گرفتن است lock()
و unlock()
به صورت دستی این کنترل دقیقی را بر روی زمانی که قفل به دست می آید و آزاد می شود، فراهم می کند.
مثال:
import java.util.concurrent.locks.ReentrantLock
class SafeCounter {
private val lock = ReentrantLock()
private var count = 0
fun increment() {
lock.lock() // Explicitly acquire the lock
try {
count++
println("Incremented to: $count")
} finally {
lock.unlock() // Ensure the lock is released even if an exception occurs
}
}
fun getCount(): Int {
lock.lock()
return try {
count
} finally {
lock.unlock()
}
}
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println("Final count: ${counter.getCount()}")
}
2. استفاده از withLock
تابع پسوند
را withLock
تابع افزونه استفاده از قفل را در Kotlin با مدیریت آن ساده می کند lock()
و unlock()
به طور خودکار تماس می گیرد.
مثال:
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class SafeList {
private val lock = ReentrantLock()
private val list = mutableListOf<String>()
fun add(item: String) {
lock.withLock {
list.add(item)
}
}
fun getList(): List<String> {
lock.withLock {
return list.toList() // Return a copy for safety
}
}
}
fun main() {
val safeList = SafeList()
val threads = List(5) { index ->
Thread {
safeList.add("Item-$index")
}
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println("Final list: ${safeList.getList()}")
}
3. استفاده از synchronized
را synchronized
کلمه کلیدی جایگزین ساده تری برای همگام سازی اولیه با قفل کردن روی یک شی مانیتور خاص ارائه می دهد.
مثال:
class SafeCounter {
private var count = 0
fun increment() {
synchronized(this) { // Synchronize on the instance itself
count++
println("Incremented to: $count")
}
}
fun getCount(): Int {
synchronized(this) {
return count
}
}
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println("Final count: ${counter.getCount()}")
}
4. استفاده از ReadWriteLock
برای سناریوهایی با خواندن مکرر و نوشتن نادر، ReadWriteLock
قفل های جداگانه ای برای خواندن و نوشتن فراهم می کند که به چندین رشته اجازه می دهد همزمان بخوانند.
مثال:
import java.util.concurrent.locks.ReentrantReadWriteLock
class SafeMap {
private val lock = ReentrantReadWriteLock()
private val map = mutableMapOf<String, String>()
fun put(key: String, value: String) {
lock.writeLock().lock()
try {
map[key] = value
} finally {
lock.writeLock().unlock()
}
}
fun get(key: String): String? {
lock.readLock().lock()
return try {
map[key]
} finally {
lock.readLock().unlock()
}
}
}
fun main() {
val safeMap = SafeMap()
val threads = List(5) { index ->
Thread { safeMap.put("Key-$index", "Value-$index") }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println("Final map: $safeMap")
}
5. استفاده از Coroutines و Mutex
برای همزمانی مبتنی بر کوروتین، کاتلین این را ارائه می دهد Mutex
کلاس از kotlinx.coroutines.sync
. این یک قفل معمولی است که از مسدود کردن نخ ها جلوگیری می کند.
مثال:
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class SafeCounter {
private val mutex = Mutex()
private var count = 0
suspend fun increment() {
mutex.withLock {
count++
println("Incremented to: $count")
}
}
fun getCount(): Int = count
}
fun main() = runBlocking {
val counter = SafeCounter()
val jobs = List(10) {
launch {
counter.increment()
}
}
jobs.forEach { it.join() }
println("Final count: ${counter.getCount()}")
}
6. استفاده از متغیرهای اتمی
برای سناریوهای ساده، متغیرهای اتمی مانند AtomicInteger
و AtomicLong
جایگزینی بدون قفل برای شمارنده ها و آکومولاتورهای ایمن با رزوه ارائه کنید.
مثال:
import java.util.concurrent.atomic.AtomicInteger
class SafeCounter {
private val count = AtomicInteger(0)
fun increment() {
println("Incremented to: ${count.incrementAndGet()}")
}
fun getCount(): Int = count.get()
}
fun main() {
val counter = SafeCounter()
val threads = List(10) {
Thread { counter.increment() }
}
threads.forEach { it.start() }
threads.forEach { it.join() }
println("Final count: ${counter.getCount()}")
}
چه زمانی از هر کدام استفاده کنیم؟
-
ReentrantLock
+lock/unlock
: برای کنترل سطح پایین استفاده کنید، به خصوص زمانی که به ویژگی های پیشرفته مانند قفل های قطع شونده نیاز است. -
withLock
: رویکرد اصطلاحی کاتلین برای بیشتر موارد استفاده. -
synchronized
: ساده و سرراست برای همگام سازی اولیه. -
ReadWriteLock
: ایده آل برای خواندن مکرر و نوشتن نادر. -
Mutex
: بهترین برای همزمانی مبتنی بر کوروتین. - متغیرهای اتمی: سبک و بدون قفل، مناسب برای شمارنده و آکومولاتور.
هر رویکرد نیازهای خاصی را بر اساس پیچیدگی، عملکرد، و اینکه آیا شما با رشتهها یا کوروتینها کار میکنید، برآورده میکند. درک این گزینه ها تضمین می کند که می توانید برنامه های همزمان ایمن و کارآمد Kotlin را بنویسید.