Ի՞նչ է Java-ի synchronized բլոկը և ինչ խնդիրներ կարող են առաջանալ դրա օգտագործման ժամանակ։
sobes.tech AI
Պատասխան AI-ից
Java-յի synchronized բլոկը օգտագործվում է ընդհանուր ռեսուրսին մուտքի սինխրոնիզացիան ապահովելու համար մի քանի թելերի միջև։ Դա երաշխավորում է, որ միայն մեկ թել կարող է կատարել բլոկի ներսում գտնվող կոդը ցանկացած ժամանակ:
synchronized բլոկի կառուցվածքը՝
synchronized (մոնիտոր_օբյեկտ) {
// Կրիտիկական հատված
// Այստեղ կատարվում են ընդհանուր ռեսուրսի հետ գործողություններ
}
մոնիտոր_օբյեկտ: ցանկացած օբյեկտ, որը ծառայում է որպես մոնիտոր (լոկ). Թելերը, որոնք փորձում են մուտք գործելsynchronizedբլոկը նույն օբյեկտով, կլանվեն մինչև որ ընթացիկ թելը դուրս գա բլոկից:
Հնարավոր խնդիրներ՝
-
Deadlock (մահացու լոկացում): Երկու կամ ավելի թելեր սպասում են ռեսուրսի ազատմանը, որը զբաղեցված է այլ թելով, ինչը հանգեցնում է ծրագրի կանգառի։ Դա կարող է տեղի ունենալ, եթե թելերը փորձում են ստանալ լոկեր տարբեր կարգով:
-
Ավելի ցածր արդյունավետություն: Սինխրոնիզացիան խոչընդոտում է մյուս թելերի կատարմանը, որոնք սպասում են մոնիտորի հասանելիությանը, ինչը կարող է դանդաղեցնել ծրագրի աշխատանքը:
-
Որոշ սցենարներում կիրառելի չէ:
synchronized-ը ապահովում է բացառիկ մուտք։ Որոշ դեպքերում կարող է անհրաժեշտ լինել ավելի ճկուն մուտքի կառավարում (օր., միաժամանակ մի քանի թելերից ընթերցում, գրառում մեկ թելից): -
Համակարգման բարդություն: Սինխրոնիզացիայի խնդիրները կարող են լինել աննկատ և դժվար վերարտադրել և դետեկցել:
Նմուշ՝
class Resource {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1(Resource other) {
synchronized (lock1) {
try {
Thread.sleep(100); // Աշխատանքի իմիտացիա
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " ձեռք բերեց lock1");
synchronized (other.lock2) {
System.out.println(Thread.currentThread().getName() + " ձեռք բերեց lock2-ի մյուսը");
}
}
}
public void method2(Resource other) {
synchronized (lock2) {
try {
Thread.sleep(100); // Աշխատանքի իմիտացիա
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " ձեռք բերեց lock2");
synchronized (other.lock1) {
System.out.println(Thread.currentThread().getName() + " ձեռք բերեց lock1-ի մյուսը");
}
}
}
}
public class DeadlockExample {
public static void main(String[] args) {
Resource r1 = new Resource();
Resource r2 = new Resource();
new Thread(() -> r1.method1(r2), "Thread-1").start();
new Thread(() -> r2.method2(r1), "Thread-2").start();
}
}
Այս օրինակով, Thread-1 փորձում է ձեռք բերել lock1-ը r1-ում և հետո lock2-ը r2-ում։ Thread-2 փորձում է ձեռք բերել lock2-ը r2-ում և հետո lock1-ը r1-ում։ Եթե նրանք ձեռք բերեն առաջին լոկերը միաժամանակ, կստեղծվի փոխադարձ լոկացում։