Java Multi-Threading Gone اشتباه: یک کابوس پس زمینه واقعی در دنیای واقعی

شما به تازگی برنامه بوت بهار با کارایی بالا را مستقر کرده اید. تا زمانی که سنبله های ترافیکی را انجام می دهد ، هموار اجرا می شود. ناگهان ، همه چیز یخبشر بدون خطا ، بدون تصادف ، فقط یک سیستم ساکت و بی پاسخ.
خوش آمدید بن بست جهنم– جایی که دو موضوع منابع را گروگان می گیرند و از عقب نشینی امتناع می ورزند.
چگونه همه چیز اشتباه شد
باطن شما دارای دو کار پس زمینه است که منابع مشترک را به روز می کنند:
- یک موضوع معاملات پایگاه داده را مدیریت می کند.
- برای سرعت بخشیدن به پاسخ ها ، حافظه مخفی را انجام می دهد.
به نظر می رسد مانند یک معماری محکم ، درست است؟ اما در یک سناریوی با کنفرانس بالا ، این موضوعات در نهایت منتظر یکدیگر می شوند و یک بن بست غیرقابل تحمل ایجاد می کنند.
کد مشکل ساز:
class Resource {
private final String name;
public Resource(String name) { this.name = name; }
public String getName() { return name; }
}
class DeadlockExample {
private final Resource resource1 = new Resource("Database Connection");
private final Resource resource2 = new Resource("Cache Layer");
public void processA() {
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " locked " + resource1.getName());
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " locked " + resource2.getName());
}
}
}
public void processB() {
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " locked " + resource2.getName());
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " locked " + resource1.getName());
}
}
}
}
public class DeadlockSimulator {
public static void main(String[] args) {
DeadlockExample system = new DeadlockExample();
Thread t1 = new Thread(system::processA, "Thread-A");
Thread t2 = new Thread(system::processB, "Thread-B");
t1.start();
t2.start();
}
}
چرا پس زمینه شما یخ زد
-
Thread-A
قفل می کند اتصال پایگاه داده و منتظر لایه حافظهبشر -
Thread-B
قفل می کند لایه حافظه و منتظر اتصال پایگاه دادهبشر - هیچ یک از موضوع نمی توانند ادامه دهند.
- پس زمینه شما متوقف می شود تا متوقف شودبشر
رفع: قفل دقیق تر
گزینه 1: سفارش قفل مداوم
همیشه قفل ها را به همان ترتیب در تمام موضوعات بدست آورید.
public void safeProcess() {
synchronized (resource1) { // Always lock DB first
System.out.println(Thread.currentThread().getName() + " locked " + resource1.getName());
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
synchronized (resource2) { // Then lock Cache
System.out.println(Thread.currentThread().getName() + " locked " + resource2.getName());
}
}
}
اکنون ، مهم نیست که چند موضوع تخم ریزی کنید ، آنها نمی گواند در انتظار یکدیگر گیر کنید.
گزینه 2: استفاده کنید tryLock()
برای جلوگیری از بن بست
به جای انتظار نامحدود ، استفاده کنید ReentrantLock.tryLock()
بنابراین اگر یک منبع در دسترس نباشد ، یک موضوع می تواند حرکت کند.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SafeResource {
private final Lock lock = new ReentrantLock();
public boolean tryLock() {
return lock.tryLock();
}
public void unlock() {
lock.unlock();
}
}
حال ، اگر یک نخ نمی توان قفل کرد، آن پشت سر گذاشتن به جای یخ زدن سیستم خود.
افکار نهایی: Taming Multi-Threading
چند رشته ای قدرتمند است ، اما بدون برخورد دقیق ، مانند بازی با Dynamite است. از بن بست توسط:
✅ همیشه قفل کردن منابع به همان ترتیب
✅ استفاده tryLock()
برای جلوگیری از انتظار نامحدود
✅ نظارت بر فعالیت موضوع با ابزارها
دفعه بعد قفل کردن، شما دقیقاً می دانید کجا باید نگاه کنید. 🚀