JavaRush /Java Blog /Random-TL /Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panay...

Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam. Bahagi 3

Nai-publish sa grupo
Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam. Bahagi 1 Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam. Bahagi 2

Multithreading

37. Paano lumikha ng isang bagong thread (daloy) sa Java?

Sa isang paraan o iba pa, ang paglikha ay nangyayari sa pamamagitan ng paggamit ng klase ng Thread. Ngunit maaaring mayroong mga pagpipilian dito ...
  1. Nagmana tayo sajava.lang.Thread
  2. Nagpapatupad kami ng isang interface java.lang.Runnablena ang object ay tumatanggap ng isang constructor Threadclass
Pag-usapan natin ang bawat isa sa kanila.

Nagmana tayo sa klase ng Thread

Upang magawa ito, sa aming klase ay nagmamana kami mula sa java.lang.Thread. Naglalaman ito ng meth run(), na kung ano mismo ang kailangan natin. Ang lahat ng buhay at lohika ng bagong thread ay nasa pamamaraang ito. Ito ay isang uri ng mainpamamaraan para sa isang bagong thread. Pagkatapos nito, ang natitira na lang ay lumikha ng object ng aming klase at isagawa ang method start(), na lilikha ng bagong thread at patakbuhin ang logic na nakasulat dito. Tingnan natin:
/**
* Пример того, How создавать треды путем наследования {@link Thread} класса.
*/
class ThreadInheritance extends Thread {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance threadInheritance1 = new ThreadInheritance();
       ThreadInheritance threadInheritance2 = new ThreadInheritance();
       ThreadInheritance threadInheritance3 = new ThreadInheritance();
       threadInheritance1.start();
       threadInheritance2.start();
       threadInheritance3.start();
   }
}
Ang output sa console ay magiging ganito:

Thread-1
Thread-0
Thread-2
Iyon ay, kahit na dito nakikita natin na ang mga thread ay naisakatuparan hindi sa turn, ngunit bilang ang JVM nagpasya)

Pagpapatupad ng Runnable na interface

Kung ikaw ay laban sa inheritance at/o inherit mo na ang isa sa iba pang klase, maaari mong gamitin ang java.lang.Runnable. Dito sa aming klase ipinapatupad namin ang interface na ito at ipinapatupad ang method run(), tulad ng sa halimbawang iyon. Kailangan mo lang lumikha ng higit pang mga bagay Thread. Mukhang mas malala pa ang mas maraming linya. Ngunit alam natin kung gaano nakakapinsala ang mana at mas mabuting iwasan ito sa lahat ng paraan ;) Tingnan natin:
/**
* Пример того, How создавать треды из интерфейса {@link Runnable}.
* Здесь проще простого - реализуем этот интерфейс и потом передаем в конструктор
* экземпляр реализуемого an object.
*/
class ThreadInheritance implements Runnable {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance runnable1 = new ThreadInheritance();
       ThreadInheritance runnable2 = new ThreadInheritance();
       ThreadInheritance runnable3 = new ThreadInheritance();

       Thread threadRunnable1 = new Thread(runnable1);
       Thread threadRunnable2 = new Thread(runnable2);
       Thread threadRunnable3 = new Thread(runnable3);

       threadRunnable1.start();
       threadRunnable2.start();
       threadRunnable3.start();
   }
}
At ang resulta ng pagpapatupad:

Thread-0
Thread-1
Thread-2

38. Ano ang pagkakaiba sa pagitan ng isang proseso at isang thread?

Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam.  Bahagi 3 - 1Mayroong mga sumusunod na pagkakaiba sa pagitan ng isang proseso at isang thread:
  1. Ang isang programa na isinasagawa ay tinatawag na isang proseso, habang ang isang Thread ay isang subset ng isang proseso.
  2. Ang mga proseso ay independyente, samantalang ang mga thread ay isang subset ng isang proseso.
  3. Ang mga proseso ay may iba't ibang address space sa memorya, habang ang mga thread ay naglalaman ng isang karaniwang address space.
  4. Ang paglipat ng konteksto ay mas mabilis sa pagitan ng mga thread kumpara sa mga proseso.
  5. Ang interprocess na komunikasyon ay mas mabagal at mas mahal kaysa sa interthread na komunikasyon.
  6. Ang anumang mga pagbabago sa proseso ng magulang ay hindi nakakaapekto sa proseso ng bata, samantalang ang mga pagbabago sa thread ng magulang ay maaaring makaapekto sa thread ng bata.

39. Ano ang mga pakinabang ng multithreading?

Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam.  Bahagi 3 - 2
  1. Ang multithreading ay nagbibigay-daan sa isang application/program na laging tumugon sa input kahit na ito ay nagpapatakbo na ng ilang mga gawain sa background;
  2. Binibigyang-daan ka ng multithreading na kumpletuhin ang mga gawain nang mas mabilis dahil ang mga thread ay iisa-isa ang pagpapatupad;
  3. Nagbibigay ang multithreading ng mas mahusay na paggamit ng cache dahil ang mga thread ay nagbabahagi ng mga karaniwang mapagkukunan ng memorya;
  4. Binabawasan ng multithreading ang dami ng server na kinakailangan dahil ang isang server ay maaaring magpatakbo ng maramihang mga thread nang sabay-sabay.

40. Ano ang mga estado sa siklo ng buhay ng isang thread?

Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam.  Bahagi 3 - 3
  1. Bago: Sa ganitong estado, ang isang object ng klase Threaday nilikha gamit ang bagong operator, ngunit ang thread ay hindi umiiral. Ang thread ay hindi magsisimula hangga't hindi natin tinatawag ang start().
  2. Runnable: Sa ganitong estado, handa nang tumakbo ang thread pagkatapos tawagan ang pamamaraan simulan(). Gayunpaman, hindi pa ito napipili ng thread scheduler.
  3. Tumatakbo: Sa ganitong estado, pipili ang thread scheduler ng thread mula sa ready state at ito ay tatakbo.
  4. Naghihintay/Naka-block: Sa ganitong estado, hindi tumatakbo ang thread ngunit buhay pa rin o naghihintay ng isa pang thread na makumpleto.
  5. Dead/Terminated: Kapag lumabas ang method, run()nasa terminated o dead state ang thread.

41. Posible bang magsimula ng thread nang dalawang beses?

Hindi, hindi namin mai-restart ang thread dahil kapag nagsimula na at naisakatuparan ang thread, mapupunta ito sa Dead state. Kaya kung susubukan naming patakbuhin ang thread ng dalawang beses, ito ay magtapon ng runtimeException " java.lang.IllegalThreadStateException ". Tingnan natin:
class DoubleStartThreadExample extends Thread {

   /**
    * Имитируем работу треда
    */
   public void run() {
	// что-то происходит. Для нас не существенно на этом этапе
   }

   /**
    * Запускаем тред дважды
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
Sa sandaling maabot ng trabaho ang pangalawang pagsisimula ng parehong thread, magkakaroon ng pagbubukod. Try it yourself ;) mas magandang makakita ng isang beses kaysa makarinig ng isang daang beses.

42. Paano kung direktang tatawagan mo ang run() method nang hindi tinatawagan ang start() method?

Oo, run()siyempre maaari kang tumawag ng isang pamamaraan, ngunit hindi ito lilikha ng isang bagong thread at isakatuparan ito bilang isang hiwalay na thread. Sa kasong ito, ito ay isang simpleng bagay na tinatawag na isang simpleng pamamaraan. Kung pinag-uusapan natin ang pamamaraan start(), ito ay ibang bagay. Sa pamamagitan ng paglulunsad ng paraang ito, runtimenaglulunsad ito ng bago at ito naman ay nagpapatakbo ng aming pamamaraan ;) Kung hindi ka naniniwala sa akin, subukan ito:
class ThreadCallRunExample extends Thread {

   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.print(i);
       }
   }

   public static void main(String args[]) {
       ThreadCallRunExample runExample1 = new ThreadCallRunExample();
       ThreadCallRunExample runExample2 = new ThreadCallRunExample();

       // просто будут вызваны в потоке main два метода, один за другим.
       runExample1.run();
       runExample2.run();
   }
}
At ang output sa console ay magiging ganito:

0123401234
Makikita na walang thread na ginawa. Lahat ay gumana tulad ng isang normal na klase. Una ang unang paraan ng klase ay gumana, pagkatapos ay ang pangalawa.

43. Ano ang thread ng daemon?

Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam.  Bahagi 3 - 4Ang Daemon thread (mula rito ay tinutukoy bilang daemon thread) ay isang thread na nagsasagawa ng mga gawain sa background na may kaugnayan sa isa pang thread. Iyon ay, ang trabaho nito ay magsagawa ng mga pantulong na gawain na kailangang gawin lamang kasabay ng isa pang (pangunahing) thread. Maraming daemon thread na awtomatikong gumagana, tulad ng Garbage Collector, finalizer, atbp.

Bakit isinasara ng Java ang thread ng daemon?

Ang tanging layunin ng isang daemon thread ay ang pagbibigay ng mga serbisyo sa thread ng gumagamit para sa gawaing suporta sa background. Samakatuwid, kung nakumpleto na ang pangunahing thread, awtomatikong isinasara ng runtime ang lahat ng mga thread ng daemon nito.

Mga pamamaraan para sa pagtatrabaho sa klase ng Thread

Nagbibigay ang klase java.lang.Threadng dalawang pamamaraan para sa pagtatrabaho sa thread na daemon:
  1. public void setDaemon(boolean status)- nagpapahiwatig na ito ay magiging isang daemon thread. Ang default ay false, na nangangahulugan na ang mga non-daemon na thread ay gagawin maliban kung tinukoy nang hiwalay.
  2. public boolean isDaemon()- mahalagang ito ay isang getter para sa variable daemonna itinakda namin gamit ang nakaraang pamamaraan.
Halimbawa:
class DaemonThreadExample extends Thread {

   public void run() {
       // Проверяет, демон ли этот поток or нет
       if (Thread.currentThread().isDaemon()) {
           System.out.println("daemon thread");
       } else {
           System.out.println("user thread");
       }
   }

   public static void main(String[] args) {
       DaemonThreadExample thread1 = new DaemonThreadExample();
       DaemonThreadExample thread2 = new DaemonThreadExample();
       DaemonThreadExample thread3 = new DaemonThreadExample();

       // теперь thread1 - поток-демон.
       thread1.setDaemon(true);

       System.out.println("демон?.. " + thread1.isDaemon());
       System.out.println("демон?.. " + thread2.isDaemon());
       System.out.println("демон?.. " + thread3.isDaemon());

       thread1.start();
       thread2.start();
       thread3.start();
   }
}
Output ng console:

демон?.. true
демон?.. false
демон?.. false
daemon thread
user thread
user thread
Mula sa output nakita natin na sa loob mismo ng thread, gamit ang isang static currentThread()na pamamaraan, malalaman natin kung aling thread ito sa isang banda, sa kabilang banda, kung mayroon tayong reference sa object ng thread na ito, malalaman natin. direkta mula dito. Nagbibigay ito ng kinakailangang flexibility sa pagsasaayos.

44. Posible bang gawing daemon ang isang thread pagkatapos itong malikha?

Hindi. Kung gagawin mo ito ito ay magtapon ng isang pagbubukod IllegalThreadStateException. Samakatuwid, maaari lamang tayong lumikha ng isang daemon thread bago ito magsimula. Halimbawa:
class SetDaemonAfterStartExample extends Thread {

   public void run() {
       System.out.println("Working...");
   }

   public static void main(String[] args) {
       SetDaemonAfterStartExample afterStartExample = new SetDaemonAfterStartExample();
       afterStartExample.start();

       // здесь будет выброшено исключение
       afterStartExample.setDaemon(true);
   }
}
Output ng console:

Working...
Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.setDaemon(Thread.java:1359)
	at SetDaemonAfterStartExample.main(SetDaemonAfterStartExample.java:14)

45. Ano ang shutdownhook?

Ang Shutdownhook ay isang thread na tahasang tinatawag bago isara ang JVM (Java Virtual Machine). Kaya't magagamit natin ito upang linisin ang isang mapagkukunan o i-save ang estado kapag ang Java Virtual Machine ay normal o biglaang nag-shut down. Maaari tayong magdagdag shutdown hookgamit ang sumusunod na pamamaraan:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Gaya ng ipinapakita sa halimbawa:
/**
* Программа, которая показывает How запустить shutdown hook тред,
* который выполнится аккурат до окончания работы JVM
*/
class ShutdownHookThreadExample extends Thread {

   public void run() {
       System.out.println("shutdown hook задачу выполнил");
   }

   public static void main(String[] args) {

       Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());

       System.out.println("Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.");
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
Output ng console:

Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.
shutdown hook задачу выполнил

46. ​​Ano ang pag-synchronize?

Ang pag-synchronize sa Java ay ang kakayahang kontrolin ang access ng maramihang mga thread sa anumang nakabahaging mapagkukunan. Kapag sinubukan ng maraming mga thread na gawin ang parehong gawain, may posibilidad ng isang maling resulta, kaya upang mapagtagumpayan ang problemang ito, gumagamit ang Java ng pag-synchronize, dahil kung saan isang thread lamang ang maaaring gumana sa isang pagkakataon. Maaaring makamit ang pag-synchronize sa tatlong paraan:
  • Paraan ng Pag-synchronize
  • Sa pamamagitan ng pag-synchronize ng isang partikular na bloke
  • Static na pag-synchronize

Pag-synchronize ng pamamaraan

Ang naka-synchronize na paraan ay ginagamit upang i-lock ang isang bagay para sa anumang nakabahaging mapagkukunan. Kapag tumawag ang isang thread sa isang naka-synchronize na paraan, awtomatiko itong nakakakuha ng lock sa bagay na iyon at ilalabas ito kapag natapos na ng thread ang gawain nito. Upang magawa ito, kailangan mong idagdag ang naka-synchronize na keyword . Tingnan natin kung paano ito gumagana sa isang halimbawa:
/**
* Пример, где мы синхронизируем метод. То есть добавляем ему слово synchronized.
* Есть два писателя, которые хотят использовать один принтер. Они подготовor свои поэмы
* И конечно же не хотят, чтоб их поэмы перемешались, а хотят, чтоб работа была сделана по * * * очереди для каждого из них
*/
class Printer {

   synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer  = new Printer();

       // создаем два треда
       Writer1 writer1 = new Writer1(printer);
       Writer2 writer2 = new Writer2(printer);

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

/**
* Писатель номер 1, который пишет свою поэму.
*/
class Writer1 extends Thread {
   Printer printer;

   Writer1(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<string> poem = Arrays.asList("Я ", this.getName(), " Пишу", " Письмо");
       printer.print(poem);
   }

}

/**
* Писатель номер 2, который пишет свою поэму.
*/
class Writer2 extends Thread {
   Printer printer;

   Writer2(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<String> poem = Arrays.asList("Не Я ", this.getName(), " Не пишу", " Не Письмо");
       printer.print(poem);
   }
}
At ang output sa console:

Я Thread-0 Пишу Письмо
Не Я Thread-1 Не пишу Не Письмо

Block ng pag-synchronize

Ang isang naka-synchronize na bloke ay maaaring gamitin upang magsagawa ng pag-synchronize sa anumang partikular na mapagkukunan ng pamamaraan. Sabihin natin na sa isang malaking paraan (oo, oo, hindi ka maaaring magsulat ng mga ganoong bagay, ngunit kung minsan ito ay nangyayari) kailangan mong i-synchronize lamang ang isang maliit na bahagi, para sa ilang kadahilanan. Kung ilalagay mo ang lahat ng mga code ng isang pamamaraan sa isang naka-synchronize na bloke, gagana ito sa parehong paraan bilang isang naka-synchronize na paraan. Ang syntax ay ganito ang hitsura:
synchronized (“an object для блокировки”) {
   // сам code, который нужно защитить
}
Upang hindi maulit ang nakaraang halimbawa, gagawa kami ng mga thread sa pamamagitan ng mga hindi kilalang klase - iyon ay, agad na ipatupad ang Runnable na interface.
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

   void print(List<String> wordsToPrint) {
       synchronized (this) {
           wordsToPrint.forEach(System.out::print);
       }
       System.out.println();
   }

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer = new Printer();

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

}
at output sa console

Я Writer1 Пишу Письмо
Не Я Writer2 Не пишу Не Письмо

Static na pag-synchronize

Kung gagawin mo ang isang static na pamamaraan na naka-synchronize, ang lock ay nasa klase, hindi sa object. Sa halimbawang ito, inilalapat namin ang naka-synchronize na keyword sa isang static na paraan upang maisagawa ang static na pag-synchronize:
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

   static synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               Printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               Printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}
at ang output sa console:

Не Я Writer2 Не пишу Не Письмо
Я Writer1 Пишу Письмо

47. Ano ang volatile variable?

Ang keyword volatileay ginagamit sa multi-threaded programming upang magbigay ng kaligtasan sa thread dahil ang isang pagbabago sa isang nababagong variable ay nakikita ng lahat ng iba pang mga thread, kaya ang isang variable ay maaaring gamitin ng isang thread sa isang pagkakataon. Gamit ang keyword, volatilemaaari mong garantiya na ang variable ay magiging thread-safe at maiimbak sa shared memory, at hindi ito dadalhin ng mga thread sa kanilang cache. Anong itsura?
private volatile AtomicInteger count;
Idagdag lang namin sa variable volatile. Ngunit hindi ito nangangahulugan ng kumpletong kaligtasan ng thread... Pagkatapos ng lahat, maaaring hindi atomic ang mga operasyon sa isang variable. Ngunit maaari mong gamitin Atomicang mga klase na gumaganap ng operasyon nang atomically, iyon ay, sa isang pagpapatupad ng processor. Maraming ganoong klase ang matatagpuan sa package java.util.concurrent.atomic.

48. Ano ang deadlock

Ang deadlock sa Java ay bahagi ng multithreading. Maaaring magkaroon ng deadlock sa isang sitwasyon kung saan naghihintay ang isang thread sa isang object lock na nakuha ng isa pang thread, at naghihintay ang isang pangalawang thread sa isang object lock na nakuha ng unang thread. Kaya, ang dalawang thread na ito ay naghihintay sa isa't isa at hindi magpapatuloy sa pagpapatupad ng kanilang code. Nangungunang 50 Java Core na Mga Tanong at Sagot sa Panayam.  Bahagi 3 - 5Tingnan natin ang isang Halimbawa kung saan mayroong isang klase na nagpapatupad ng Runnable. Tumatanggap ito ng dalawang mapagkukunan sa constructor nito. Sa loob ng run() na pamamaraan, kinakailangan ang lock para sa kanila nang paisa-isa, kaya kung gagawa ka ng dalawang object ng klase na ito at ililipat ang mga mapagkukunan sa iba't ibang mga order, madali kang makakapasok sa isang lock:
class DeadLock {

   public static void main(String[] args) {
       final Integer r1 = 10;
       final Integer r2 = 15;

       DeadlockThread threadR1R2 = new DeadlockThread(r1, r2);
       DeadlockThread threadR2R1 = new DeadlockThread(r2, r1);

       new Thread(threadR1R2).start();
       new Thread(threadR2R1).start();
   }
}

/**
* Класс, который принимает два ресурса.
*/
class DeadlockThread implements Runnable {

   private final Integer r1;
   private final Integer r2;

   public DeadlockThread(Integer r1, Integer r2) {
       this.r1 = r1;
       this.r2 = r2;
   }

   @Override
   public void run() {
       synchronized (r1) {
           System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r1);

           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }

           synchronized (r2) {
               System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r2);
           }
       }
   }
}
Output ng console:

Первый тред захватил первый ресурс
Второй тред захватывает второй ресурс

49. Paano maiwasan ang deadlock?

Batay sa nalalaman natin kung paano nagkakaroon ng deadlock, makakagawa tayo ng ilang konklusyon...
  • Tulad ng ipinakita sa halimbawa sa itaas, ang deadlock ay dahil sa nesting ng mga kandado. Ibig sabihin, sa loob ng isang lock ay may isa pa o higit pa. Maiiwasan ito sa sumusunod na paraan - sa halip na mag-nest, kailangan mong magdagdag ng bagong abstraction sa itaas at bigyan ang lock sa mas mataas na antas, at alisin ang mga nested lock.
  • Ang mas maraming pagharang, mas malaki ang posibilidad na magkaroon ng deadlock. Samakatuwid, sa tuwing magdadagdag ka ng lock, kailangan mong pag-isipan kung talagang kailangan ito at kung maiiwasan ba ang pagdaragdag ng bago.
  • Gumagamit ng Thread.join(). Ang isang deadlock ay maaari ding gawin kapag ang isang thread ay naghihintay para sa isa pa. Upang maiwasan ang problemang ito, maaari mong isaalang-alang ang pagtatakda ng limitasyon sa oras sa join()pamamaraan.
  • Kung may isang thread tayo, walang deadlock ;)

50. Ano ang kondisyon ng lahi?

Kung sa mga totoong karera ay gumaganap ang mga kotse, pagkatapos ay sa terminolohiya ng karera ng multi-threading, ang mga thread ay gumaganap sa mga karera. Pero bakit? Mayroong dalawang thread na tumatakbo at maaaring magkaroon ng access sa parehong bagay. At maaari nilang subukang i-update ang estado nang sabay-sabay. So far malinaw naman lahat diba? Kaya't ang mga thread ay gumagana alinman sa totoong parallel (kung mayroong higit sa isang core sa processor) o kondisyon na kahanay, kapag ang processor ay naglalaan ng isang maikling panahon. At hindi namin makokontrol ang mga prosesong ito, kaya hindi namin magagarantiya na kapag ang isang thread ay nagbasa ng data mula sa isang bagay, magkakaroon ito ng oras upang baguhin ito BAGO gawin ito ng ibang thread. Ang mga problemang tulad nito ay nangyayari kapag ang kumbinasyong pagsubok-at-kilos na ito ay dumaan. Ano ang ibig sabihin nito? Halimbawa, mayroon tayong ifexpression sa katawan kung saan nagbabago ang kundisyon, iyon ay:
int z = 0;

// проверь
if (z < 5) {
//действуй
   z = z + 5;
}
Kaya't maaaring mayroong isang sitwasyon kapag ang dalawang thread ay sabay-sabay na pumapasok sa bloke ng code na ito sa isang pagkakataon kung kailan ang z ay katumbas pa rin ng zero at magkasama nilang binabago ang halagang ito. At sa huli ay hindi natin makukuha ang inaasahang halaga na 5, ngunit 10. Paano ito maiiwasan? Kailangan mong i-lock bago at pagkatapos ng pagpapatupad. Iyon ay, para sa unang thread na pumasok sa block if, gawin ang lahat ng mga aksyon, baguhin ito, zat pagkatapos lamang bigyan ang susunod na thread ng pagkakataon na gawin ito. Ngunit ang susunod na thread ay hindi papasok sa block if, dahil zito ay magiging katumbas ng 5:
// получить блокировку для z
if (z < 5) {
   z = z + 5;
}
// выпустить из блокировки z
===================================================

Sa halip na output

Gusto kong magpasalamat sa lahat ng nagbabasa hanggang sa huli. Ito ay isang mahabang paglalakbay at nagawa mo ito! Maaaring hindi malinaw ang lahat. Ito ay mabuti. Sa sandaling nagsimula akong mag-aral ng Java, hindi ko maipalibot ang aking ulo sa kung ano ang isang static na variable. Ngunit wala, natulog ako sa pag-iisip na ito, nagbasa ng ilang higit pang mga mapagkukunan at sa wakas ay naunawaan. Ang paghahanda para sa isang pakikipanayam ay higit pa sa isang akademikong bagay kaysa sa isang praktikal. Samakatuwid, bago ang bawat panayam, kailangan mong ulitin at i-refresh ang iyong memorya ng mga bagay na maaaring hindi mo madalas gamitin.

At gaya ng dati, kapaki-pakinabang na mga link:

Salamat sa lahat sa pagbabasa, See you soon) Aking profile sa GitHub
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION