تفصيلن جو هڪ مختصر جائزو ته ڪيئن موضوعن سان تعلق رکن ٿا. اڳي، اسان ڏٺو ته ڪئين سلسلا هڪ ٻئي سان هم وقت ساز ٿين ٿا. هن ڀيري اسان انهن مسئلن تي غور ڪنداسين جيڪي پيدا ٿي سگهن ٿيون جيئن موضوعن جي وچ ۾ لهه وچڙ ۾، ۽ اسان ان بابت ڳالهائينداسين ته انهن کان ڪيئن بچجي. اسان وڌيڪ تفصيلي مطالعي لاءِ ڪجهه مفيد لنڪ پڻ فراهم ڪنداسين.
هڪ JVisualVM پلگ ان انسٽال ٿيل (ذريعي اوزار -> پلگ ان) سان، اسان ڏسي سگهون ٿا ته ڊيڊ لاڪ ڪٿي ٿيو آهي:
JVisualVM جي مطابق، اسان ننڊ جا دور ۽ پارڪ جو دور ڏسون ٿا (اهو اهو آهي جڏهن هڪ ڌاڳو هڪ تالا حاصل ڪرڻ جي ڪوشش ڪري ٿو - اهو پارڪ اسٽيٽ ۾ داخل ٿئي ٿو، جيئن اسان اڳ ۾ بحث ڪيو جڏهن اسان موضوع جي هم وقت سازي بابت ڳالهايو )
. توھان ھتي لائيو لاڪ جو ھڪڙو مثال ڏسي سگھو ٿا: Java - Thread Livelock
.
توهان هتي هڪ بهترين مثال ڏسي سگهو ٿا: Java - Thread Starvation and Fairness
. هي مثال ڏيکاري ٿو ته ٿريڊن سان ڇا ٿئي ٿو بک جي دوران ۽ ڪيئن هڪ ننڍڙي تبديلي توهان کي لوڊ کي برابر طور تي ورهائڻ جي اجازت ڏئي ٿي
هي انسپيڪشن IntelliJ IDEA ۾ شامل ڪيو ويو مسئلو IDEA-61117
جي حصي طور، جيڪو 2010 ۾ رليز نوٽس
۾ درج ڪيو ويو .

تعارف
تنهن ڪري، اسان ڄاڻون ٿا ته جاوا موضوع آهن. توھان ان جي باري ۾ پڙھي سگھوٿا جائزي ۾ عنوان سان گڏ بهتر: جاوا ۽ ٿريڊ ڪلاس. حصو I - عملدرآمد جا سلسلا . ۽ اسان ان حقيقت کي دريافت ڪيو ته موضوع هڪ ٻئي سان هم وقت سازي ڪري سگهن ٿا جائزي ۾ هڪ ٻئي سان گڏ بهتر: جاوا ۽ ٿريڊ ڪلاس. حصو II - هم وقت سازي . اهو وقت ڳالهائڻ جو وقت آهي ته موضوع ڪيئن هڪ ٻئي سان لهه وچڙ ۾. اهي حصيداري وسيلن کي ڪيئن حصيداري ڪندا آهن؟ هتي ڪهڙا مسئلا پيدا ٿي سگهن ٿا؟
تعطل
سڀ کان خوفناڪ مسئلو تعطل آهي. Deadlock اهو آهي جڏهن ٻه يا وڌيڪ سلسلا هميشه لاء ٻئي جي انتظار ۾ آهن. اسان Oracle ويب پيج مان ھڪڙو مثال کڻنداسين جيڪو بيان ڪري ٿو ڊيڊ لاڪ :public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
}
}
ڊيڊ لاڪ هتي پهريون ڀيرو نه ٿي سگھي، پر جيڪڏهن توهان جو پروگرام هينگ ٿئي ٿو، ته پوءِ اهو وقت آهي هلڻ جو jvisualvm
: 
"Thread-1" - Thread t@12
java.lang.Thread.State: BLOCKED
at Deadlock$Friend.bowBack(Deadlock.java:16)
- waiting to lock <33a78231> (a Deadlock$Friend) owned by "Thread-0" t@11
ٿريڊ 1 ٿريڊ 0 مان بند ٿيڻ جو انتظار ڪري رهيو آهي. ائين ڇو ٿو ٿئي؟ Thread-1
هلڻ شروع ٿئي ٿو ۽ Friend#bow
طريقي سان عمل ڪري ٿو. اهو synchronized
لفظ سان نشان لڳايو ويو آهي، جنهن جو مطلب آهي ته اسان مانيٽر حاصل ڪري رهيا آهيون this
(موجوده اعتراض). طريقو جو ان پٽ ٻئي Friend
اعتراض جو حوالو هو. هاڻي، Thread-1
ٻئي تي طريقي سان عمل ڪرڻ چاهي ٿو Friend
، ۽ ائين ڪرڻ لاء ان جو تالا حاصل ڪرڻ گهرجي. پر جيڪڏهن ٻيو ڌاڳو (هن صورت ۾ Thread-0
) طريقي سان داخل ٿيڻ ۾ ڪامياب ٿي ويو bow()
، پوء تالا اڳ ۾ ئي حاصل ڪيو ويو آهي ۽ Thread-1
انتظار ڪري ٿو Thread-0
، ۽ ان جي برعڪس. اهو تعطل ناقابل حل آهي، ۽ اسان ان کي تعطل سڏيو آهي. موت جي گرفت وانگر جيڪو آزاد نه ٿو ڪري سگهجي، تعطل هڪ باهمي بلاڪ آهي جنهن کي ٽوڙي نٿو سگهجي. Deadlock جي ٻي وضاحت لاءِ، توھان ھي وڊيو ڏسي سگھو ٿا: Deadlock ۽ Livelock وضاحت ڪئي وئي
.
چريو
جيڪڏهن اتي تعطل آهي، ته اتي به چرپر آهي؟ ها، اتي آهي :) لائيو لاڪ تڏهن ٿيندو آهي جڏهن ڌاڙا ٻاهران زنده نظر اچن ٿا، پر اهي ڪجهه به ڪرڻ جي قابل نه هوندا آهن، ڇاڪاڻ ته انهن لاءِ ڪم جاري رکڻ لاءِ جيڪي شرط گهربل هوندا آهن، اهي پورا نه ٿي سگهندا آهن. بنيادي طور تي، لائيو لاڪ ڊيڊ لاڪ سان ملندڙ جلندڙ آهي، پر موضوع هڪ مانيٽر جي انتظار ۾ "هنگ" نٿا ڪن. ان جي بدران، اهي هميشه لاء ڪجهه ڪري رهيا آهن. مثال طور:import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class App {
public static final String ANSI_BLUE = "\u001B[34m";
public static final String ANSI_PURPLE = "\u001B[35m";
public static void log(String text) {
String name = Thread.currentThread().getName(); // Like "Thread-1" or "Thread-0"
String color = ANSI_BLUE;
int val = Integer.valueOf(name.substring(name.lastIndexOf("-") + 1)) + 1;
if (val != 0) {
color = ANSI_PURPLE;
}
System.out.println(color + name + ": " + text + color);
try {
System.out.println(color + name + ": wait for " + val + " sec" + color);
Thread.currentThread().sleep(val * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Lock first = new ReentrantLock();
Lock second = new ReentrantLock();
Runnable locker = () -> {
boolean firstLocked = false;
boolean secondLocked = false;
try {
while (!firstLocked || !secondLocked) {
firstLocked = first.tryLock(100, TimeUnit.MILLISECONDS);
log("First Locked: " + firstLocked);
secondLocked = second.tryLock(100, TimeUnit.MILLISECONDS);
log("Second Locked: " + secondLocked);
}
first.unlock();
second.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(locker).start();
new Thread(locker).start();
}
}
هن ڪوڊ جي ڪاميابي ان ترتيب تي منحصر آهي جنهن ۾ جاوا ٿريڊ شيڊيولر ٿريڊز کي شروع ڪري ٿو. جيڪڏهن Thead-1
پهرين شروع ٿئي ٿي، ته پوءِ اسان لائيو لاڪ حاصل ڪريون ٿا:
Thread-1: First Locked: true
Thread-1: wait for 2 sec
Thread-0: First Locked: false
Thread-0: wait for 1 sec
Thread-0: Second Locked: true
Thread-0: wait for 1 sec
Thread-1: Second Locked: false
Thread-1: wait for 2 sec
Thread-0: First Locked: false
Thread-0: wait for 1 sec
...
جئين توهان مثال مان ڏسي سگهو ٿا، ٻنهي موضوعن کي موڙ ۾ ٻنهي تالا حاصل ڪرڻ جي ڪوشش ڪئي، پر اهي ناڪام ٿيا. پر، اهي تعطل ۾ نه آهن. ٻاهران، سڀ ڪجهه ٺيڪ آهي ۽ اهي پنهنجو ڪم ڪري رهيا آهن. 
بُک
تعطل ۽ لائيو لاڪ کان علاوه، هڪ ٻيو مسئلو آهي جيڪو ملٽي ٿريڊنگ دوران ٿي سگهي ٿو: بکيو. اهو رجحان بلاڪ ڪرڻ جي پوئين شڪلن کان مختلف آهي جنهن ۾ موضوعن کي بلاڪ نه ڪيو ويو آهي - انهن وٽ صرف ڪافي وسيلا نه آهن. نتيجي طور، جڏهن ته ڪجهه موضوعن تي عمل ڪرڻ جو وقت وٺندو آهي، ٻيا هلائڻ جي قابل نه هوندا آهن:
https://www.logicbig.com/
Thread.sleep()
.Thread.wait()

نسل جون حالتون
multithreading ۾، اتي هڪ "نسل حالت" جي طور تي هڪ شيء آهي. اهو رجحان تڏهن ٿئي ٿو جڏهن ٿريڊز هڪ وسيلو شيئر ڪن ٿا، پر ڪوڊ اهڙي طريقي سان لکيو ويو آهي ته جيئن اهو صحيح شيئرنگ کي يقيني نه بڻائي. هڪ مثال ڏسو:public class App {
public static int value = 0;
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
int oldValue = value;
int newValue = ++value;
if (oldValue + 1 != newValue) {
throw new IllegalStateException(oldValue + " + 1 = " + newValue);
}
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
هي ڪوڊ شايد پهريون ڀيرو غلطي پيدا نه ڪري سگھي. جڏهن اهو ٿئي ٿو، اهو شايد هن طرح نظر اچي ٿو:
Exception in thread "Thread-1" java.lang.IllegalStateException: 7899 + 1 = 7901
at App.lambda$main$0(App.java:13)
at java.lang.Thread.run(Thread.java:745)
جئين توهان ڏسي سگهو ٿا، ڪجهه غلط ٿي ويو جڏهن newValue
هڪ قيمت مقرر ڪئي وئي هئي. newValue
تمام وڏو آهي. value
نسل جي حالت جي ڪري، ھڪڙي سلسلي کي ٻن بيانن جي وچ ۾ متغير کي تبديل ڪرڻ ۾ مدد ڪئي . اهو معلوم ٿئي ٿو ته سلسلي جي وچ ۾ هڪ نسل آهي. هاڻي سوچيو ته اهو ڪيترو ضروري آهي ته مانيٽري ٽرانزيڪشن سان اهڙيون غلطيون نه ڪيون وڃن... مثال ۽ ڊراگرام پڻ هتي ڏسي سگهجن ٿا: جاوا سلسلي ۾ نسل جي حالت کي ترتيب ڏيڻ لاءِ ڪوڊ
.
اُٿلندڙ
موضوعن جي رابطي جي باري ۾ ڳالهائيندي،volatile
لفظ قابل ذڪر آهي. اچو ته هڪ سادي مثال ڏسو:
public class App {
public static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Runnable whileFlagFalse = () -> {
while(!flag) {
}
System.out.println("Flag is now TRUE");
};
new Thread(whileFlagFalse).start();
Thread.sleep(1000);
flag = true;
}
}
سڀ کان وڌيڪ دلچسپ، اهو تمام گهڻو ڪم نه ڪرڻ جو امڪان آهي. نئون ٿريڊ فيلڊ ۾ تبديلي نه ڏسندو flag
. فيلڊ لاءِ ھن کي درست ڪرڻ لاءِ flag
، اسان کي لفظ استعمال ڪرڻ گھرجي volatile
. ڪيئن ۽ ڇو؟ پروسيسر سڀني عملن کي انجام ڏئي ٿو. پر حسابن جا نتيجا ضرور محفوظ ڪيا وڃن. ان لاءِ مکيه ياداشت آهي ۽ پروسيسر جي ڪيش آهي. پروسيسر جا ڪيش ميموري جي هڪ ننڍڙي حصي وانگر هوندا آهن جيڪي ڊيٽا تائين رسائي حاصل ڪرڻ لاءِ استعمال ڪيا ويندا آهن جڏهن ته مکيه ميموري تائين رسائي حاصل ڪرڻ کان وڌيڪ جلدي. پر هر شيءِ جو هڪ پاسو آهي: ڪيش ۾ ڊيٽا اپڊيٽ نه ٿي سگھي (جيئن مٿي ڏنل مثال ۾، جڏهن پرچم فيلڊ جي قيمت اپڊيٽ نه ڪئي وئي هئي). تنهن ڪري، volatile
لفظ JVM کي ٻڌائي ٿو ته اسان اسان جي متغير کي ڪيش ڪرڻ نٿا چاهيون. هي اجازت ڏئي ٿو ته تازه ترين نتيجا سڀني موضوعن تي ڏسڻ لاءِ. هي هڪ انتهائي آسان وضاحت آهي. جيئن ته volatile
لفظي لفظ لاء، مان تمام گهڻو سفارش ڪريان ٿو ته توهان هي مضمون
پڙهو . وڌيڪ معلومات لاءِ، مان توهان کي جاوا ميموري ماڊل
۽ Java Volatile Keyword
پڙهڻ جي پڻ صلاح ڏيان ٿو . اضافي طور تي، اهو ياد رکڻ ضروري آهي ته اهو volatile
ڏسڻ جي باري ۾ آهي، ۽ تبديلين جي جوهر بابت نه. "ريس حالتون" سيڪشن ۾ ڪوڊ کي ڏسي، اسان IntelliJ IDEA ۾ هڪ ٽول ٽائپ ڏسندا: 
ايٽمي
ايٽمي آپريشنز اهي آپريشن آهن جن کي ورهائي نٿو سگهجي. مثال طور، متغير کي قيمت تفويض ڪرڻ جو عمل ايٽمي هجڻ گهرجي. بدقسمتي سان، واڌارو آپريشن ايٽمي نه آهي، ڇاڪاڻ ته واڌارو جي ضرورت آهي ٽي سي پي يو آپريشنز: پراڻي قيمت حاصل ڪريو، ان ۾ هڪ شامل ڪريو، پوء قيمت بچايو. ايٽمي اهميت ڇو آهي؟ انڪريمينٽ آپريشن سان، جيڪڏهن ڪا نسل جي حالت آهي، ته پوءِ گڏيل وسيلو (يعني گڏيل قدر) اوچتو ڪنهن به وقت تبديل ٿي سگهي ٿو. اضافي طور تي، آپريشن شامل آهن 64-bit جوڙجڪ، مثال طورlong
۽ double
، ايٽمي نه آهن. وڌيڪ تفصيل هتي پڙهي سگهجن ٿا: 64-bit ويلز پڙهڻ ۽ لکڻ دوران ايٽمي کي يقيني بڻايو
. ايٽمي سان لاڳاپيل مسئلا هن مثال ۾ ڏسي سگهجن ٿا:
public class App {
public static int value = 0;
public static AtomicInteger atomic = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
value++;
atomic.incrementAndGet();
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
Thread.sleep(300);
System.out.println(value);
System.out.println(atomic.get());
}
}
خاص AtomicInteger
طبقو هميشه اسان کي 30,000 ڏيندو، پر value
وقت وقت تي تبديل ٿيندو. ھن موضوع جو ھڪڙو مختصر جائزو آھي: جاوا ۾ ايٽمي متغيرن جو تعارف
. "مقابلي ۽ ادل بدل" الورورٿم ايٽمي طبقن جي دل تي واقع آهي. توھان ان بابت وڌيڪ پڙھي سگھوٿا ھتي لاڪ فري الگورٿمز جي مقابلي ۾ - CAS ۽ FAA جي مثال تي JDK 7 ۽ 8
يا وڪيپيڊيا تي موازن ۽ ادل جي مضمون ۾.

http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
ٿئي ٿو- اڳي
هتي هڪ دلچسپ ۽ پراسرار تصور آهي جنهن کي "اڳ ۾ ٿئي ٿو" سڏيو ويندو آهي. توهان جي موضوعن جي مطالعي جي حصي جي طور تي، توهان کي ان بابت پڙهڻ گهرجي. واقعن کان اڳ جو تعلق اهو حڪم ڏيکاري ٿو جنهن ۾ سلسلي جي وچ ۾ عمل ڏٺو ويندو. ڪيتريون ئي تفسير ۽ تبصرا آهن. هتي هن موضوع تي سڀ کان تازي پيش ڪيل پيشين مان هڪ آهي: جاوا "هپين-کان اڳ" تعلقات .خلاصو
هن جائزي ۾، اسان ڪجهه تفصيلن جي ڳولا ڪئي آهي ته ڪئين موضوع ڪيئن لهه وچڙ ڪن ٿا. اسان انهن مسئلن تي بحث ڪيو جيڪي پيدا ٿي سگهن ٿا، انهي سان گڏ انهن کي سڃاڻڻ ۽ ختم ڪرڻ جا طريقا. موضوع تي اضافي مواد جي فهرست:- ٻه ڀيرا چيڪ ٿيل تالا
- JSR 133 (Java Memory Model) FAQ
- IQ 35: تعطل کي ڪيئن روڪيو؟
- ڊگلس هاڪنس (2017) پاران جاوا ۾ گڏيل تصورات
GO TO FULL VERSION