JavaRush /جاوا بلاگ /Random-SD /توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II -...
Viacheslav
سطح

توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي

گروپ ۾ شايع ٿيل

تعارف

تنهن ڪري، اسان ڄاڻون ٿا ته جاوا ۾ موضوع آهن، جن بابت توهان جائزو ۾ پڙهي سگهو ٿا " توهان جاوا کي هڪ موضوع سان خراب نه ٿا ڪري سگهو: حصو I - موضوع ". هڪ ئي وقت ڪم ڪرڻ لاءِ سلسلا گهربل آهن. تنهن ڪري، اهو تمام گهڻو امڪان آهي ته موضوع ڪنهن به طرح هڪ ٻئي سان لهه وچڙ ڪندو. اچو ته سمجهون ته اهو ڪيئن ٿئي ٿو ۽ اسان وٽ ڪهڙا بنيادي ڪنٽرول آهن. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 1

حاصلات

Thread.yield() طريقو پراسرار آهي ۽ گهٽ ۾ گهٽ استعمال ٿيندو آهي. انٽرنيٽ تي ان جي وضاحت جا ڪيترائي مختلف قسم آهن. ايتري تائين جو ڪجهه لکن ٿا ته ٿريڊن جي هڪ قطار جي باري ۾، جنهن ۾ سٽون پنهنجي ترجيحات کي نظر ۾ رکندي هيٺ لهي وينديون آهن. ڪو لکي ٿو ته ٿريڊ ان جي اسٽيٽس مٽائي هلندي هلڻ جي قابل ٿي ويندي (جيتوڻيڪ انهن اسٽيٽس ۾ ڪا به تقسيم ناهي، ۽ جاوا انهن جي وچ ۾ فرق نٿو ڪري). پر حقيقت ۾، سڀڪنھن شيء کي تمام گهڻو وڌيڪ نامعلوم آهي ۽، هڪ معنى ۾، سادو. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 2طريقي جي دستاويز جي موضوع تي، yieldاتي هڪ بگ آهي " JDK-6416721: (spec thread) Fix Thread.yield() javadoc ". جيڪڏهن توهان ان کي پڙهو، اهو واضح آهي ته حقيقت ۾ اهو طريقو yieldصرف جاوا ٿريڊ شيڊولر کي ڪجهه سفارشون ڏئي ٿو ته هن سلسلي کي گهٽ وقت تي عمل ڪرڻ جي اجازت ڏئي سگهجي ٿي. پر اصل ۾ ڇا ٿيندو، ڇا شيڊولر سفارش کي ٻڌندو ۽ اھو ڇا ڪندو عام طور تي JVM ۽ آپريٽنگ سسٽم جي عمل تي منحصر آھي. يا شايد ڪجهه ٻين عنصرن کان. سڀ مونجهارو گهڻو ڪري جاوا ٻولي جي ترقي دوران multithreading جي ٻيهر سوچڻ جي ڪري هو. توھان وڌيڪ پڙھي سگھوٿا جائزو ۾ " جاوا جو مختصر تعارف Thread.yield() ".

سمهڻ - سمهڻ وارو سلسلو

هڪ ڌاڳو ان جي عمل دوران ننڊ ڪري سگهي ٿو. اهو ٻين موضوعن سان رابطي جو آسان ترين قسم آهي. آپريٽنگ سسٽم جنهن تي جاوا ورچوئل مشين لڳل آهي، جتي جاوا ڪوڊ لڳايو ويندو آهي، ان جو پنهنجو ٿريڊ شيڊيولر هوندو آهي، جنهن کي Thread Scheduler چئبو آهي. اھو اھو آھي جيڪو فيصلو ڪري ٿو ته ڪھڙي سلسلي کي ڪڏھن هلائڻو آھي. پروگرامر هن شيڊيولر سان سڌو سنئون جاوا ڪوڊ مان رابطو نٿو ڪري سگهي، پر هو، JVM ذريعي، شيڊيولر کان پڇي ٿو ته ٿريڊ کي ٿوري دير لاءِ روڪي، ”ان کي سمهڻ لاءِ. توھان وڌيڪ پڙھي سگھوٿا مضمونن ۾ " Thread.sleep() " and " How Multithreading works ". ان کان علاوه، توهان ڳولي سگهو ٿا ته ڪئين موضوع ونڊوز OS ۾ ڪم ڪن ٿا: " اندروني ونڊوز ٿريڊ ". هاڻي اسان ان کي پنهنجي اکين سان ڏسنداسين. اچو ته هيٺ ڏنل ڪوڊ کي فائل ۾ محفوظ ڪريون HelloWorldApp.java:
class HelloWorldApp {
    public static void main(String []args) {
        Runnable task = () -> {
            try {
                int secToWait = 1000 * 60;
                Thread.currentThread().sleep(secToWait);
                System.out.println("Waked up");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}
جئين توهان ڏسي سگهو ٿا، اسان وٽ هڪ ڪم آهي جيڪو 60 سيڪنڊن جو انتظار ڪري ٿو، جنهن کان پوء پروگرام ختم ٿئي ٿو. اسان گڏ ڪريون javac HelloWorldApp.java۽ هلون java HelloWorldApp. اهو بهتر آهي ته هڪ الڳ ونڊو ۾ لانچ ڪرڻ. مثال طور، ونڊوز تي اهو هن طرح هوندو: start java HelloWorldApp. jps ڪمانڊ استعمال ڪندي، اسان پروسيس جي PID ڳوليندا آهيون ۽ ٿريڊز جي لسٽ کي استعمال ڪندي کوليو jvisualvm --openpid pidПроцесса: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 3جيئن توهان ڏسي سگهو ٿا، اسان جو ٿريڊ ننڊ جي حالت ۾ داخل ٿي چڪو آهي. حقيقت ۾، موجوده سلسلي کي سمهڻ وڌيڪ خوبصورت طريقي سان ڪري سگهجي ٿو:
try {
	TimeUnit.SECONDS.sleep(60);
	System.out.println("Waked up");
} catch (InterruptedException e) {
	e.printStackTrace();
}
توهان شايد محسوس ڪيو آهي ته اسان هر جڳهه تي عمل ڪيو آهي InterruptedException؟ اچو ته سمجھون ڇو.

ڪنهن سلسلي ۾ مداخلت يا Thread.interrupt

شيء اها آهي ته جڏهن ڌاڳو خواب ۾ انتظار ڪري رهيو آهي، ڪو ماڻهو هن انتظار ۾ مداخلت ڪرڻ چاهي ٿو. انهي حالت ۾، اسان اهڙي استثنا کي سنڀاليندا آهيون. اهو طريقو Thread.stopختم ٿيڻ کان پوءِ ڪيو ويو، يعني. پراڻي ۽ استعمال لاء ناپسنديده. ان جو سبب اهو هو ته جڏهن اهو طريقو سڏيو ويو ته stopموضوع صرف "ماريو ويو" هو، جيڪو بلڪل غير متوقع هو. اسان کي خبر ناهي ته وهڪري کي روڪيو ويندو، اسان ڊيٽا جي تسلسل جي ضمانت نه ڏئي سگهيا آهيون. تصور ڪريو ته توهان هڪ فائل ڏانهن ڊيٽا لکي رهيا آهيو ۽ پوء وهڪرو تباهه ٿي ويو آهي. تنهن ڪري، اسان فيصلو ڪيو ته اهو وڌيڪ منطقي هوندو ته وهڪري کي مارڻ نه، پر ان کي خبر ڏيو ته ان ۾ مداخلت ڪئي وڃي. ان تي ڪيئن رد عمل ڪجي اهو خود وهڪري تي منحصر آهي. وڌيڪ تفصيل ڳولي سگهجن ٿا Oracle جي " Why is Thread.stop deprecated؟ " اچو ته هڪ مثال ڏسو:
public static void main(String []args) {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(60);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
هن مثال ۾، اسان 60 سيڪنڊن جو انتظار نه ڪنداسين، پر فوري طور تي 'Interrupted' کي پرنٽ ڪنداسين. اهو ئي سبب آهي جو اسان ٿريڊ جو طريقو سڏيو آهي interrupt. اهو طريقو "اندروني پرچم سڏيو ويندو آهي مداخلت واري حيثيت" کي سيٽ ڪري ٿو. اهو آهي، هر سلسلي ۾ هڪ اندروني پرچم آهي جيڪو سڌو سنئون نه آهي. پر اسان وٽ هن پرچم سان لهه وچڙ لاءِ مقامي طريقا آهن. پر اهو واحد طريقو ناهي. ھڪڙو سلسلو عمل جي عمل ۾ ٿي سگھي ٿو، ڪنھن شيء جي انتظار ۾ نه، پر صرف عملن کي انجام ڏيڻ. پر اهو مهيا ڪري سگهي ٿو ته اهي ان کي پنهنجي ڪم ۾ هڪ خاص نقطي تي مڪمل ڪرڻ چاهيندا. مثال طور:
public static void main(String []args) {
	Runnable task = () -> {
		while(!Thread.currentThread().isInterrupted()) {
			//Do some work
		}
		System.out.println("Finished");
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.interrupt();
}
مٿي ڏنل مثال ۾، توهان ڏسي سگهو ٿا ته لوپ whileهلندو جيستائين ڌاڳو ٻاهران مداخلت نه ڪيو وڃي. isInterrupted flag بابت ڄاڻڻ لاءِ اهم شيءِ اها آهي ته جيڪڏهن اسان ان کي پڪڙينداسين InterruptedException، پرچم isInterruptedري سيٽ ڪيو ويندو، ۽ پوءِ isInterruptedاهو غلط موٽندو. ٿريڊ ڪلاس ۾ ھڪڙو جامد طريقو پڻ آھي جيڪو صرف موجوده سلسلي تي لاڳو ٿئي ٿو - Thread.interrupted() ، پر اھو طريقو پرچم کي غلط ڏانھن ري سيٽ ڪري ٿو! توھان وڌيڪ پڙھي سگھوٿا باب ۾ " Thread Interruption ".

شامل ٿيو - ٻئي سلسلي جي مڪمل ٿيڻ جو انتظار

سڀ کان سادي قسم جو انتظار آهي ٻئي سلسلي جي مڪمل ٿيڻ جو.
public static void main(String []args) throws InterruptedException {
	Runnable task = () -> {
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	};
	Thread thread = new Thread(task);
	thread.start();
	thread.join();
	System.out.println("Finished");
}
هن مثال ۾، نئون موضوع 5 سيڪنڊن لاء ننڊ ڪندو. ساڳئي وقت، مکيه ڌاڳو انتظار ڪندو جيستائين سمهڻ وارو سلسلو جاڳندو ۽ پنهنجو ڪم پورو ڪري. جيڪڏهن توهان JVisualVM ذريعي ڏسو، موضوع جي حالت هن طرح نظر ايندي: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 4مانيٽرنگ اوزار جي مهرباني، توهان ڏسي سگهو ٿا ته ڇا ٿي رهيو آهي موضوع سان. طريقو joinبلڪل سادو آهي، ڇاڪاڻ ته اهو صرف جاوا ڪوڊ سان هڪ طريقو آهي جيڪو عمل ڪري ٿو waitجڏهن ته موضوع جنهن تي ان کي سڏيو ويندو آهي زنده آهي. هڪ دفعو ڌاڳو مري ويندو آهي (ختم ٿيڻ تي)، انتظار ختم ڪيو ويندو آهي. اهو طريقو جو سڄو جادو آهي join. تنهن ڪري، اچو ته سڀ کان دلچسپ حصو ڏانهن وڃو.

تصور مانيٽر

multithreading ۾ مانيٽر وانگر هڪ شيء آهي. عام طور تي، لفظ مانيٽر لاطيني مان ترجمو ڪيو ويو آهي "نگران" يا "نگران." هن آرٽيڪل جي فريم ورڪ ۾، اسان مضمون کي ياد ڪرڻ جي ڪوشش ڪنداسين، ۽ انهن لاء جيڪي چاهيندا آهن، آئون توهان کان پڇان ٿو ته تفصيل لاء لنڪس مان مواد ۾ ٻڏڻ لاء. اچو ته پنهنجو سفر شروع ڪريون جاوا ٻولي جي وضاحت سان، يعني JLS سان: " 17.1. هم وقت سازي ". اهو هيٺيان چوي ٿو: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 5اهو ظاهر ٿئي ٿو ته موضوعن جي وچ ۾ هم وقت سازي جي مقصد لاء، جاوا هڪ خاص ميڪانيزم استعمال ڪري ٿو جنهن کي "مانيٽر" سڏيو ويندو آهي. هر شئي ان سان لاڳاپيل هڪ مانيٽر آهي، ۽ موضوع ان کي لاڪ يا ان لاڪ ڪري سگهو ٿا. اڳيون، اسان Oracle ويب سائيٽ تي هڪ تربيتي سبق ڳولينداسين: “ Intrinsic Locks and Synchronization ”. هي سبق وضاحت ڪري ٿو ته جاوا ۾ هم وقت سازي هڪ اندروني اداري جي چوڌاري ٺهيل آهي جنهن کي هڪ اندروني تالا يا مانيٽر لاک طور سڃاتو وڃي ٿو. گهڻو ڪري اهڙي تالا صرف هڪ "مانيٽر" سڏيو ويندو آهي. اسان وري ڏسون ٿا ته جاوا ۾ هر شئي جو ان سان لاڳاپيل هڪ اندروني تالا آهي. توهان پڙهي سگهو ٿا " جاوا - اندروني لاڪ ۽ هم وقت سازي ". اڳيون، اهو سمجهڻ ضروري آهي ته جاوا ۾ هڪ اعتراض ڪيئن مانيٽر سان لاڳاپيل ٿي سگهي ٿو. جاوا ۾ هر شئي جو هيڊر هوندو آهي - هڪ قسم جو اندروني ميٽا ڊيٽا جيڪو ڪوڊ مان پروگرامر وٽ موجود ناهي، پر جنهن کي ورچوئل مشين کي شين سان صحيح طريقي سان ڪم ڪرڻ جي ضرورت آهي. اعتراض جي هيڊر ۾ هڪ MarkWord شامل آهي جيڪو هن وانگر ڏسڻ ۾ اچي ٿو: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 6

https://edu.netbeans.org/contrib/slides/java-overview-and-java-se6.pdf

حبر مان هڪ مضمون هتي تمام مفيد آهي: " پر ملٽي ٿريڊنگ ڪيئن ڪم ڪندو آهي؟ حصو I: هم وقت سازي ." هن آرٽيڪل ۾ اهو هڪ وضاحت شامل ڪرڻ جي قابل آهي ٽاسڪ بلاڪ جي خلاصو JDK بگٽيڪر کان: “ JDK-8183909 ”. ساڳي شيء توهان " JEP-8183909 " ۾ پڙهي سگهو ٿا. تنهن ڪري، جاوا ۾، هڪ مانيٽر هڪ اعتراض سان لاڳاپيل آهي ۽ موضوع هن سلسلي کي بلاڪ ڪري سگهي ٿو، يا اهي پڻ چوندا آهن "لاڪ حاصل ڪريو". سادو مثال:
public class HelloWorld{
    public static void main(String []args){
        Object object = new Object();
        synchronized(object) {
            System.out.println("Hello World");
        }
    }
}
تنهن ڪري، لفظ استعمال ڪندي، synchronizedموجوده ٿريڊ (جنهن ۾ ڪوڊ جون اهي لائينون لڳل آهن) استعمال ڪرڻ جي ڪوشش ڪري ٿو مانيٽر سان جڙيل اعتراض object۽ "لاک حاصل ڪريو" يا "مانيٽر کي پڪڙيو" (ٻيو اختيار اڃا به بهتر آهي). جيڪڏهن مانيٽر لاءِ ڪو به تڪرار نه آهي (يعني ٻيو ڪو به ساڳيو اعتراض تي هم وقت سازي ڪرڻ نٿو چاهي)، جاوا ڪوشش ڪري سگهي ٿو هڪ اصلاح کي انجام ڏيڻ لاءِ جنهن کي "بيزڊ لاڪنگ" سڏيو ويندو آهي. مارڪ ورڊ ۾ اعتراض جي عنوان سان لاڳاپيل ٽيگ ۽ هڪ رڪارڊ هوندو جنهن سان مانيٽر ڳنڍيل آهي. مانيٽر کي پڪڙڻ وقت هي مٿي کي گھٽائي ٿو. جيڪڏهن مانيٽر اڳ ۾ ئي ڪنهن ٻئي سلسلي سان ڳنڍيو ويو آهي، پوء هي تالا ڪافي نه آهي. JVM ايندڙ لاڪنگ جي قسم ڏانھن سوئچ ڪري ٿو - بنيادي لاڪنگ. اهو استعمال ڪري ٿو compare-and-swap (CAS) آپريشن. ساڳئي وقت، مارڪ ورڊ ۾ هيڊر هاڻي مارڪ ورڊ کي پاڻ ۾ محفوظ نه ڪندو آهي، پر ان جي اسٽوريج لاء هڪ لنڪ + ٽيگ تبديل ڪيو ويو آهي ته جيئن JVM سمجهي ته اسان بنيادي لاڪنگ استعمال ڪري رهيا آهيون. جيڪڏهن ڪيترن ئي موضوعن جي مانيٽر لاء تڪرار آهي (هڪ مانيٽر تي قبضو ڪيو ويو آهي، ۽ ٻيو مانيٽر جي جاري ٿيڻ جو انتظار ڪري رهيو آهي)، پوء مارڪ ورڊ ۾ ٽيگ تبديل ٿي، ۽ مارڪ ورڊ مانيٽر جي حوالي سان ذخيرو ڪرڻ شروع ڪري ٿو. هڪ اعتراض - JVM جو ڪجهه اندروني ادارو. جيئن JEP ۾ چيو ويو آهي، هن صورت ۾، هن اداري کي ذخيرو ڪرڻ لاءِ اصلي هيپ ياداشت واري علائقي ۾ جاءِ گهربل آهي. ھن اندروني اداري جي اسٽوريج جي جڳھ جي لنڪ مارڪ ورڊ اعتراض ۾ واقع ٿيندي. اهڙيء طرح، جيئن اسان ڏسون ٿا، مانيٽر واقعي هڪ ميکانيزم آهي جنهن کي يقيني بڻائڻ لاء ڪيترن ئي موضوعن جي رسائي جي هم وقت سازي کي يقيني بڻائڻ لاء گڏيل وسيلن تائين. ھن ميکانيزم جا ڪيترائي عمل آھن جن جي وچ ۾ JVM سوئچ ڪري ٿو. تنهن ڪري، سادگي لاء، جڏهن مانيٽر بابت ڳالهائيندي، اسان اصل ۾ تالا بابت ڳالهائي رهيا آهيون. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 7

هم وقت سازي ۽ لاڪ جي انتظار ۾

مانيٽر جو تصور، جيئن اسان اڳ ۾ ڏٺو، ويجھي طور تي "هم وقت سازي بلاڪ" جي تصور سان لاڳاپيل آهي (يا، ان کي پڻ سڏيو ويندو آهي، هڪ نازڪ سيڪشن). اچو ته هڪ مثال ڏسو:
public static void main(String[] args) throws InterruptedException {
	Object lock = new Object();

	Runnable task = () -> {
		synchronized (lock) {
			System.out.println("thread");
		}
	};

	Thread th1 = new Thread(task);
	th1.start();
	synchronized (lock) {
		for (int i = 0; i < 8; i++) {
			Thread.currentThread().sleep(1000);
			System.out.print("  " + i);
		}
		System.out.println(" ...");
	}
}
هتي، مکيه موضوع پهريون ڪم موڪلي ٿو نئين سلسلي ڏانهن، ۽ پوء فوري طور تي "ڪپچر" لاڪ ۽ ان سان گڏ هڪ ڊگهو آپريشن انجام ڏئي ٿو (8 سيڪنڊ). هن وقت، ڪم ​​ان جي عمل لاء بلاڪ ۾ داخل نه ٿو ڪري سگهجي synchronized، ڇاڪاڻ ته تالا اڳ ۾ ئي قبضو آهي. جيڪڏهن هڪ ڌاڳو هڪ تالا حاصل نٿو ڪري سگهي، اهو ان لاء مانيٽر تي انتظار ڪندو. جيترو جلد ان کي حاصل ڪري، ان تي عمل جاري رهندو. جڏهن هڪ ڌاڳو مانيٽر کي ڇڏي ٿو، اهو تالا جاري ڪري ٿو. JVisualVM ۾ اهو هن طرح نظر ايندو: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 8جئين توهان ڏسي سگهو ٿا، JVisualVM ۾ اسٽيٽس کي "مانيٽر" سڏيو ويندو آهي ڇاڪاڻ ته موضوع کي بلاڪ ڪيو ويو آهي ۽ مانيٽر تي قبضو نٿو ڪري سگهي. توھان پڻ ڳولھي سگھو ٿا موضوع جي حالت ڪوڊ ۾، پر ھن رياست جو نالو JVisualVM شرطن سان ٺھيل نه آھي، جيتوڻيڪ اھي ساڳيا آھن. انهي صورت ۾، th1.getState()لوپ forواپس ايندي BLOCKED ، ڇاڪاڻ ته جڏهن لوپ هلندي آهي، مانيٽر تي lockقبضو ڪيو ويندو آهي mainڌاڳو، ۽ ڌاڳو th1بلاڪ ڪيو ويندو آهي ۽ ڪم جاري نه رکي سگهندو آهي جيستائين تالا واپس نه اچي. هم وقت سازي بلاڪ جي اضافي ۾، هڪ مڪمل طريقو هم وقت ٿي سگهي ٿو. مثال طور، طبقي مان هڪ طريقو HashTable:
public synchronized int size() {
	return count;
}
وقت جي هڪ يونٽ ۾، اهو طريقو صرف هڪ سلسلي سان عمل ڪيو ويندو. پر اسان کي تالا جي ضرورت آهي، صحيح؟ ها مون کي ان جي ضرورت آهي. اعتراض جي طريقن جي صورت ۾، تالا ٿيندو this. هتي هن موضوع تي هڪ دلچسپ بحث آهي: " ڇا ڪو فائدو آهي هڪ هم وقت سازي وارو طريقو استعمال ڪرڻ جي بدران هڪ هم وقت ساز بلاڪ جي؟ ". جيڪڏهن طريقو جامد آهي، ته پوء تالا نه ٿيندو this(جيئن ته جامد طريقي لاء اهو نه ٿي سگهي ٿو this)، پر طبقاتي اعتراض (مثال طور، Integer.class).

انتظار ڪريو ۽ مانيٽر تي انتظار ڪريو. سڀني طريقن کي اطلاع ۽ اطلاع ڏيو

سلسلي ۾ هڪ ٻيو انتظار جو طريقو آهي، جيڪو مانيٽر سان ڳنڍيل آهي. ان جي برعڪس sleep۽ join، اهو صرف نه ٿو سڏيو وڃي. ۽ هن جو نالو آهي wait. اهو طريقو waitان اعتراض تي عمل ڪيو ويو آهي جنهن جي مانيٽر تي اسان انتظار ڪرڻ چاهيون ٿا. اچو ته هڪ مثال ڏسون:
public static void main(String []args) throws InterruptedException {
	    Object lock = new Object();
	    // task будет ждать, пока его не оповестят через lock
	    Runnable task = () -> {
	        synchronized(lock) {
	            try {
	                lock.wait();
	            } catch(InterruptedException e) {
	                System.out.println("interrupted");
	            }
	        }
	        // После оповещения нас мы будем ждать, пока сможем взять лок
	        System.out.println("thread");
	    };
	    Thread taskThread = new Thread(task);
	    taskThread.start();
        // Ждём и после этого забираем себе лок, оповещаем и отдаём лок
	    Thread.currentThread().sleep(3000);
	    System.out.println("main");
	    synchronized(lock) {
	        lock.notify();
	    }
}
JVisualVM ۾ اهو هن طرح نظر ايندو: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 10اهو سمجهڻ لاءِ ته اهو ڪيئن ڪم ڪري ٿو، توهان کي ياد رکڻ گهرجي ته طريقن جو waitحوالو notifyڏيو java.lang.Object. اهو عجيب لڳي ٿو ته موضوع سان لاڳاپيل طريقا آهن Object. پر هتي ئي جواب آهي. جيئن اسان کي ياد آهي، جاوا ۾ هر شئي هڪ هيڊر آهي. هيڊر مختلف خدمت جي معلومات تي مشتمل آهي، بشمول مانيٽر بابت معلومات- لاڪنگ اسٽيٽ بابت ڊيٽا. ۽ جيئن اسان ياد رکون ٿا، هر شئي (يعني هر مثال) جي اندروني JVM اداري سان تعلق آهي جنهن کي اندروني تالا سڏيو ويندو آهي، جنهن کي مانيٽر پڻ سڏيو ويندو آهي. مٿين مثال ۾، ڪم بيان ڪري ٿو ته اسان سان لاڳاپيل مانيٽر تي هم وقت سازي بلاڪ داخل ڪيو lock. جيڪڏهن اهو ممڪن آهي ته هن مانيٽر تي تالا حاصل ڪرڻ، پوء wait. هن ٽاسڪ تي عمل ڪرڻ وارو سلسلو مانيٽر کي جاري ڪندو lock، پر مانيٽر تي نوٽيفڪيشن جي انتظار ۾ ٿريڊن جي قطار ۾ شامل ٿيندو lock. سلسلي جي هن قطار کي WAIT-SET سڏيو ويندو آهي، جيڪو وڌيڪ صحيح طور تي جوهر کي ظاهر ڪري ٿو. اهو هڪ قطار کان وڌيڪ هڪ سيٽ آهي. موضوع mainٽاسڪ ٽاسڪ سان هڪ نئون ٿريڊ ٺاهي ٿو، ان کي شروع ڪري ٿو ۽ 3 سيڪنڊن جو انتظار ڪري ٿو. هي اجازت ڏئي ٿو، هڪ اعلي درجي جي امڪان سان، هڪ نئين سلسلي کي ڇڪڻ لاء موضوع کان اڳ تالا ڪڍڻ main۽ مانيٽر تي قطار ڪرڻ. جنهن کان پوءِ ٿريڊ mainپاڻ سنڪرونائيزيشن بلاڪ ۾ داخل ٿئي ٿو lock۽ مانيٽر تي ٿريڊ جي نوٽيفڪيشن کي انجام ڏئي ٿو. نوٽيفڪيشن موڪلڻ کان پوءِ، ٿريڊ mainمانيٽر کي رليز ڪري ٿو lock، ۽ نئون ٿريڊ (جيڪو اڳ ۾ انتظار ڪري رهيو هو) lockمانيٽر جي جاري ٿيڻ جي انتظار کان پوءِ عمل جاري رکي ٿو. اهو ممڪن آهي ته هڪ نوٽيفڪيشن صرف هڪ سلسلي ( notify) ڏانهن يا قطار ۾ سڀني موضوعن ڏانهن هڪ ڀيرو ( notifyAll) ڏانهن. توھان وڌيڪ پڙھي سگھوٿا " Notify() ۽ notifyAll() جي وچ ۾ جاوا ۾ فرق ". اهو نوٽ ڪرڻ ضروري آهي ته نوٽيفڪيشن آرڊر JVM جي عمل تي منحصر آهي. توھان وڌيڪ پڙھي سگھوٿا " notify and notifyall سان بکھري کي ڪيئن حل ڪجي؟ ". هم وقت سازي کي بغير ڪنهن اعتراض جي وضاحت ڪري سگهجي ٿو. اهو ٿي سگهي ٿو جڏهن ڪوڊ جو هڪ الڳ حصو هم وقت سازي ناهي، پر هڪ مڪمل طريقو. مثال طور، جامد طريقن لاءِ تالا هوندو طبقاتي اعتراض (حاصل ڪيو ويو .class):
public static synchronized void printA() {
	System.out.println("A");
}
public static void printB() {
	synchronized(HelloWorld.class) {
		System.out.println("B");
	}
}
تالا استعمال ڪرڻ جي لحاظ کان، ٻئي طريقا ساڳيا آهن. جيڪڏهن طريقو جامد نه آهي، پوء هم وقت سازي کي موجوده جي مطابق ڪيو ويندو instance، اهو آهي، مطابق this. رستي ۾، اڳ ۾ اسان چيو آهي ته طريقو استعمال ڪندي getStateتوهان هڪ موضوع جي حيثيت حاصل ڪري سگهو ٿا. تنهن ڪري هتي هڪ ٿريڊ آهي جيڪو مانيٽر طرفان قطار ۾ رکيل آهي، صورتحال WAITING يا TIMED_WAITING هوندي جيڪڏهن طريقي سان waitانتظار جي وقت جي حد مقرر ڪئي وئي آهي. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 11

زندگيءَ جو سلسلو

جيئن ته اسان ڏٺو آهي، وهڪري زندگي جي دوران پنهنجي حيثيت کي تبديل ڪري ٿو. ذات ۾، اهي تبديليون سلسلي جي زندگي چڪر آهن. جڏهن هڪ موضوع صرف ٺهيل آهي، ان کي نئين حيثيت حاصل آهي. هن پوزيشن ۾، اهو اڃا تائين شروع نه ڪيو ويو آهي ۽ جاوا موضوع جي شيڊولر اڃا تائين نئين موضوع بابت ڪجهه به نه ڄاڻيو آهي. سلسلي جي شيڊيولر کي ٿريڊ بابت ڄاڻڻ لاءِ، توھان کي ڪال ڪرڻ گھرجي thread.start(). پوءِ ٿريڊ هليو ويندو RUNNABLE حالت ۾. انٽرنيٽ تي ڪيتريون ئي غلط اسڪيمون آھن جتي رننبل ۽ رننگ رياستون الڳ آھن. پر هي هڪ غلطي آهي، ڇاڪاڻ ته ... جاوا "هلائڻ لاءِ تيار" ۽ "هلندڙ" حالتن جي وچ ۾ فرق نٿو ڪري. جڏهن هڪ ڌاڳو زنده آهي پر فعال نه آهي (چلڻ لائق نه آهي)، اهو ٻن رياستن مان هڪ ۾ آهي:
  • بلاڪ ٿيل - محفوظ ٿيل حصي ۾ داخلا جو انتظار ڪري ٿو، يعني. synchonizedبلاڪ ڏانهن .
  • انتظار - حالت جي بنياد تي ٻئي سلسلي جو انتظار ڪري ٿو. جيڪڏهن حالت صحيح آهي، ٿريڊ شيڊولر ٿريڊ شروع ڪندو.
جيڪڏهن هڪ موضوع وقت جي انتظار ۾ آهي، اهو TIMED_WAITING حالت ۾ آهي. جيڪڏهن ٿريڊ هاڻي نه هلي رهيو آهي (ڪاميابيءَ سان يا ڪنهن استثنا سان)، اهو ختم ٿيل حالت ۾ وڃي ٿو. ھڪڙي سلسلي جي حالت (ان جي حالت) کي ڳولڻ لاء، طريقو استعمال ڪيو ويندو آھي getState. موضوعن ۾ پڻ ھڪڙو طريقو آھي isAliveجيڪو صحيح موٽائي ٿو جيڪڏھن موضوع ختم نه ڪيو ويو آھي.

LockSupport ۽ موضوع پارڪنگ

جاوا 1.6 کان وٺي اتي ھڪڙو دلچسپ ميکانيزم ھو جنھن کي LockSupport سڏيو ويندو آھي . توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 12هي طبقو هڪ "پرمٽ" يا اجازت سان لاڳاپيل هر سلسلي سان جيڪو ان کي استعمال ڪري ٿو. طريقو ڪال parkفوري طور تي واپس اچي ٿو جيڪڏهن هڪ پرمٽ موجود آهي، ڪال جي دوران ساڳئي پرمٽ تي قبضو ڪندي. ٻي صورت ۾ اهو بند ڪيو ويندو. ڪال ڪرڻ جو طريقو unparkاجازت ڏئي ٿو ته دستياب هجي جيڪڏهن اهو اڳ ۾ ئي موجود ناهي. هتي صرف 1 اجازت آهي. جاوا API ۾، LockSupportهڪ خاص Semaphore. اچو ته هڪ سادي مثال ڏسو:
import java.util.concurrent.Semaphore;
public class HelloWorldApp{

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(0);
        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            // Просим разрешение и ждём, пока не получим его
            e.printStackTrace();
        }
        System.out.println("Hello, World!");
    }
}
هي ڪوڊ هميشه لاء انتظار ڪندو ڇو ته سيمفور هاڻي 0 پرمٽ آهي. ۽ جڏهن ڪوڊ ۾ سڏيو وڃي ٿو acquire(يعني، اجازت جي درخواست ڪريو)، موضوع انتظار ڪري ٿو جيستائين ان کي اجازت نه ملي. جيئن ته اسان انتظار ڪري رهيا آهيون، اسان ان تي عمل ڪرڻ جا پابند آهيون InterruptedException. دلچسپ ڳالهه اها آهي ته، هڪ سيمفور هڪ الڳ موضوع واري رياست کي لاڳو ڪري ٿو. جيڪڏهن اسان JVisualVM ۾ ڏسون ٿا، اسان ڏسنداسين ته اسان جي رياست انتظار نه آهي، پر پارڪ. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو II - هم وقت سازي - 13اچو ته هڪ ٻيو مثال ڏسو:
public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            //Запаркуем текущий поток
            System.err.println("Will be Parked");
            LockSupport.park();
            // Как только нас распаркуют - начнём действовать
            System.err.println("Unparked");
        };
        Thread th = new Thread(task);
        th.start();
        Thread.currentThread().sleep(2000);
        System.err.println("Thread state: " + th.getState());

        LockSupport.unpark(th);
        Thread.currentThread().sleep(2000);
}
سلسلي جي حالت انتظار ۾ هوندي، پر JVisualVM waitکان synchronized۽ parkکان وچ ۾ فرق ڪري ٿو LockSupport. هي هڪ ايترو اهم ڇو آهي LockSupport؟ اچو ته ٻيهر جاوا API ڏانهن وڃو ۽ ڏسو Thread State WAITING . جئين توهان ڏسي سگهو ٿا، ان ۾ حاصل ڪرڻ لاء صرف ٽي طريقا آهن. 2 طريقا - هي wait۽ join. ۽ ٽيون آهي LockSupport. جاوا ۾ تالا ساڳيا اصولن تي ٺهيل آهن LockSupport۽ اعلي سطحي اوزار جي نمائندگي ڪن ٿا. اچو ته ھڪڙو استعمال ڪرڻ جي ڪوشش ڪريو. اچو ته ڏسو، مثال طور، تي ReentrantLock:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class HelloWorld{

    public static void main(String []args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Runnable task = () -> {
            lock.lock();
            System.out.println("Thread");
            lock.unlock();
        };
        lock.lock();

        Thread th = new Thread(task);
        th.start();
        System.out.println("main");
        Thread.currentThread().sleep(2000);
        lock.unlock();
    }
}
جيئن اڳئين مثالن ۾، هتي هر شيء سادو آهي. lockڪنهن کي وسيلو ڇڏڻ جو انتظار ڪري ٿو. جيڪڏهن اسان JVisualVM ۾ ڏسون ٿا، اسان ڏسنداسين ته نئون ٿريڊ پارڪ ڪيو ويندو جيستائين mainٿريڊ ان کي تالا نه ڏئي. توهان لاڪ جي باري ۾ وڌيڪ هتي پڙهي سگهو ٿا: " جاوا 8 ۾ ملٽي ٿريڊ پروگرامنگ. حصو ٻيو. مٽائيندڙ شين تائين رسائي کي هم وقت سازي ڪرڻ " ۽ " جاوا لاک API. نظريو ۽ استعمال جو مثال ." لاڪ جي نفاذ کي بهتر سمجهڻ لاءِ، اهو مفيد آهي ته Phazer بابت جائزو " Phaser Class " ۾ پڙهو. ۽ مختلف هم وقت سازن جي باري ۾ ڳالهائڻ، توهان کي پڙهڻ گهرجي Habré تي مضمون “ Java.util.concurrent.* Synchronizers Reference ”.

ڪُل

هن جائزي ۾، اسان ڏٺو ته مکيه طريقن جا موضوع جاوا ۾ لهه وچڙ ۾. اضافي مواد: #وياچسلاو
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION