3.1 Aktibong bagay

Ang Active object ay isang pattern ng disenyo na naghihiwalay sa execution thread ng isang method mula sa thread kung saan ito tinawag. Ang layunin ng pattern na ito ay magbigay ng parallel execution gamit ang asynchronous method calls at isang request processing scheduler.

Pinasimpleng bersyon:

aktibong bagay

Klasikong variant:

Aktibong bagay 2

Ang template na ito ay may anim na elemento:

  • Isang proxy object na nagbibigay ng interface sa mga pampublikong pamamaraan ng kliyente.
  • Isang interface na tumutukoy sa mga paraan ng pag-access para sa aktibong bagay.
  • Listahan ng mga papasok na kahilingan mula sa mga kliyente.
  • Isang scheduler na tumutukoy sa pagkakasunud-sunod ng mga query na isasagawa.
  • Pagpapatupad ng mga aktibong pamamaraan ng object.
  • Isang callback procedure o isang variable para makatanggap ang kliyente ng resulta.

3.2 lock

Ang Lock pattern ay isang mekanismo ng pag-synchronize na nagbibigay-daan para sa eksklusibong pag-access sa isang nakabahaging mapagkukunan sa pagitan ng maraming mga thread. Ang mga kandado ay isang paraan para ipatupad ang patakaran sa pagkontrol ng concurrency.

Karaniwan, ginagamit ang isang malambot na lock, na may pag-aakalang sinusubukan ng bawat thread na "kunin ang lock" bago i-access ang kaukulang ibinahaging mapagkukunan.

Gayunpaman, ang ilang mga system ay nagbibigay ng isang mandatoryong mekanismo ng pag-lock kung saan ang isang hindi awtorisadong pagtatangka sa pag-access sa isang naka-lock na mapagkukunan ay maaabort sa pamamagitan ng paglalagay ng isang pagbubukod sa thread na nagtangkang makakuha ng access.

Ang isang semaphore ay ang pinakasimpleng uri ng lock. Sa mga tuntunin ng pag-access ng data, walang ginawang pagkakaiba sa pagitan ng mga mode ng pag-access: nakabahagi (read-only) o eksklusibo (read-write). Sa shared mode, maraming thread ang maaaring humiling ng lock para ma-access ang data sa read-only na mode. Ginagamit din ang eksklusibong access mode sa pag-update at pagtanggal ng mga algorithm.

pattern ng lock

Ang mga uri ng mga kandado ay nakikilala sa pamamagitan ng diskarte ng pagharang sa pagpapatuloy ng pagpapatupad ng thread. Sa karamihan ng mga pagpapatupad, pinipigilan ng isang kahilingan para sa isang lock ang thread na magpatuloy sa pag-execute hanggang sa maging available ang naka-lock na mapagkukunan.

Ang spinlock ay isang lock na naghihintay sa isang loop hanggang sa mabigyan ng access. Ang ganitong lock ay napakahusay kung ang isang thread ay naghihintay para sa isang lock sa isang maliit na halaga ng oras, kaya iniiwasan ang labis na muling pag-iskedyul ng mga thread. Ang halaga ng paghihintay para sa pag-access ay magiging makabuluhan kung ang isa sa mga thread ay humawak ng lock sa loob ng mahabang panahon.

pattern ng lock 2

Upang epektibong maipatupad ang mekanismo ng pag-lock, kailangan ang suporta sa antas ng hardware. Maaaring ipatupad ang suporta sa hardware bilang isa o higit pang mga atomic na operasyon gaya ng "test-and-set", "fetch-and-add" o "compare-and-swap". Ang ganitong mga tagubilin ay nagbibigay-daan sa iyo upang suriin nang walang pagkaantala na ang lock ay libre, at kung gayon, pagkatapos ay makuha ang lock.

3.3 Subaybayan

Ang Monitor pattern ay isang mataas na antas na proseso ng interaksyon at mekanismo ng pag-synchronize na nagbibigay ng access sa mga nakabahaging mapagkukunan. Isang diskarte sa pag-synchronize ng dalawa o higit pang mga gawain sa computer gamit ang isang karaniwang mapagkukunan, kadalasang hardware o isang hanay ng mga variable.

Sa multitasking na nakabatay sa monitor, malinaw na ipinapasok ng compiler o interpreter ang lock-unlock code sa naaangkop na naka-format na mga gawain, na malinaw sa programmer, na nagliligtas sa programmer mula sa tahasang pagtawag sa mga primitive ng synchronization.

Ang monitor ay binubuo ng:

  • isang hanay ng mga pamamaraan na nakikipag-ugnayan sa isang nakabahaging mapagkukunan
  • mutex
  • mga variable na nauugnay sa mapagkukunang ito
  • isang invariant na tumutukoy sa mga kundisyon upang maiwasan ang isang kundisyon ng lahi

Kinukuha ng monitor procedure ang mutex bago simulan ang trabaho at hinahawakan ito hanggang sa lumabas ang procedure o hanggang sa maghintay ng isang partikular na kondisyon. Kung ginagarantiyahan ng bawat pamamaraan na totoo ang invariant bago ilabas ang mutex, walang gawain ang makakakuha ng resource sa isang kondisyon ng lahi.

Ito ay kung paano gumagana ang naka-synchronize na operator sa Java gamit ang wait()at mga pamamaraan notify().

3.4 I-double check ang pag-lock

Ang double checked locking ay isang parallel na pattern ng disenyo na nilalayon upang bawasan ang overhead ng pagkuha ng lock.

Una, sinusuri ang kundisyon ng pagharang nang walang anumang pag-synchronize. Sinusubukan lamang ng isang thread na kumuha ng lock kung ang resulta ng pagsusuri ay nagpapahiwatig na kailangan nitong makuha ang lock.

//Double-Checked Locking
public final class Singleton {
private static Singleton instance; //Don't forget volatile modifier

public static Singleton getInstance() {
     if (instance == null) {                //Read

         synchronized (Singleton.class) {    //
             if (instance == null) {         //Read Write
                 instance = new Singleton(); //
             }
         }
     }
 }

Paano lumikha ng isang singleton object sa isang thread-safe na kapaligiran?

public static Singleton getInstance() {
   if (instance == null)
    instance = new Singleton();
}

Kung lumikha ka ng isang bagay na Singleton mula sa iba't ibang mga thread, maaaring mayroong isang sitwasyon kung saan ang ilang mga bagay ay nilikha sa parehong oras, at ito ay hindi katanggap-tanggap. Samakatuwid, makatwirang balutin ang paglikha ng bagay sa isang naka-synchronize na pahayag.

public static Singleton getInstance() {
    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

Ang diskarte na ito ay gagana, ngunit mayroon itong maliit na downside. Matapos malikha ang bagay, sa tuwing susubukan mong makuha ito sa hinaharap, isang tseke ang isasagawa sa naka-synchronize na bloke, na nangangahulugan na ang kasalukuyang thread at lahat ng konektado dito ay mai-lock. Kaya ang code na ito ay maaaring ma-optimize nang kaunti:

public static Singleton getInstance() {
     if (instance != null)
        return instance;

    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

Sa ilang mga wika at/o sa ilang mga makina, hindi posible na ligtas na ipatupad ang pattern na ito. Samakatuwid, kung minsan ito ay tinatawag na isang anti-pattern. Ang ganitong mga tampok ay humantong sa paglitaw ng "nangyayari bago" mahigpit na pagkakasunud-sunod na relasyon sa Java Memory Model at ang C++ Memory Model.

Karaniwan itong ginagamit upang bawasan ang overhead ng pagpapatupad ng tamad na pagsisimula sa mga multi-threaded na programa, gaya ng pattern ng disenyo ng Singleton. Sa tamad na pagsisimula ng isang variable, ang pagsisimula ay ipinagpaliban hanggang sa kailanganin ang halaga ng variable sa pagtutuos.

3.5 Tagapag-iskedyul

Ang Scheduler ay isang parallel na pattern ng disenyo na nagbibigay ng mekanismo para sa pagpapatupad ng isang patakaran sa pag-iiskedyul, ngunit independyente sa anumang partikular na patakaran. Kinokontrol ang pagkakasunud-sunod kung saan ang mga thread ay dapat magsagawa ng sequential code, gamit ang isang bagay na tahasang tumutukoy sa pagkakasunud-sunod ng naghihintay na mga thread.