Kimikal na Pampaya; Inhinyeriya ng Materyales
Pag-iwas sa Karaniwang mga Pagkakamali Kapag Nag-implementasyon ng Halimbawang Singleton sa Multi-threaded Engineering applications
Table of Contents
Introduction: Ang Halimbawa ng Singleton sa Multi-Threed Engineering Refictions
Ang huwarang Singleton ay isa sa mga pinaka malawak na ginagamit na disenyong disenyo sa software engineering. Tinitiyak nito na ang isang klase ay may isang pagkakataon lamang at nagbibigay ng isang pandaigdigang punto ng access sa pangyayaring iyon. Sa isang-threaded applications, ang pagpapatupad ng isang solongton ay prangka: gawin ang gusalidor pribado, magbigay ng isang statistikal na paraan na nagbibigay ng isang pagkakataon na muling lumikha ng isang ady o lazily. Gayunpaman, sa multi-threadwated engineering application application application applications na fecle tulad ng mga sistemang na naka-frequen, high-free-freeved na real-time control, ang mga sistemang mahusay na mga ins na hindi tiyak na mga ins, at mga ins na mga ins na ins na mga inscregregregregreged na mga intebtion, mga intebly reption na mga intebption, mga intebbeight.net.net. Ang mga integth.net.net.
Sinusuri ng artikulong ito ang pinaka-karaniwang mga pagkakamaling ginagawa ng mga developer kapag nagpapatupad ng singleton pattern sa mga kapaligirang may multi-threaded, nagpapaliwanag ng mga dahilan, at nagbibigay ng komprehensibong set ng mga pinakamahusay na gawain at mga dibuho upang maiwasan ang mga ito.Kalakip din dito ang mga praktikal na kodigong halimbawa sa Java, na may mga reperensiya sa mga katumbas na mga dibuho sa C+++ at C#, at nagmumungkahi ng panlabas na mapagkukunan para sa higit pang pagbasa.
Karaniwang mga Pagkakamali sa Implementasyon ng Ingglatera
Kahit ang makaranasang mga developer ay maaaring mahulog sa bitag kapag nagpapatupad ng mga isahangton sa mga sistemang nag - uugnay.
1. Hindi Ginagawang Pribado ang Segurador
Ang pundasyon ng anumang isang langton ay isang pribadong computer na humahadlang sa panlabas na instantiation. Kung ang konstructor ay madaling makuha (public, protektado, o pakete-private), anumang sinulid ay maaaring lumikha ng isang bagong pagkakataon, pagbasag sa isang kontrata ng nag-iisangton. Sa multi-threaded code, ito ay maaaring mangyari nang hindi sinasadya kapag ang isang klase ay muling nai-record at ang construction subconductor ay hindi sinasadyang binabago, o kapag ang klase ay subculat na may labis na pag-iingat-husay na pag-iwas (bagaman ang isang dokumento ay karaniwang downcreadcreadcread).
2. Hindi Natutugunan ang Pang - ibabaw na Kaligtasan
Sa isang kapaligirang may iisang-tuwirang paunang-bisa, ang isang payak na tamad na panimulang pag-iisip ay gumaganang mainam:
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Ngunit sa isang multi-threaded application, ang dalawa o higit pang mga sinulid ay maaaring sabay na pumasok sa check bago ang anumang sinulid ay lumikha ng pagkakataon. ang bawat sinulid ay pagkatapos ay gumagawa ng sarili nitong bagay, na lumalabag sa padron.Ito ay isang klasikong race na kondisyon na nagbubunga sa maraming pagkakataon at maaaring humantong sa hindi maayos na estado o mga source inters.
3. Paggamit ng Lazy Initization Nang Walang Wastong Synchronization
Halimbawa, kung kinikilala ng mga developer na nangangailangan ng ligtas na sinulid, ang paraang ito ay kadalasan nang walang - muwang na nagdaragdag ng mga bahagi ng kanilang katawan: "Ang lahat ng ay gumagana pero ang nangyayari ay hindi naman gaanong gumagana:
public static synchronized Singleton getInstance() { ... }
Sa bawat pagtawag sa ay kumukuha at naglalabas ng kandado, kahit na malikha na ang pagkakataon. sa mga senaryong high-contension, ang bandang ito sa itaas ay maaaring lubhang mapahina sa pamamagitan ngput. Ang mas mabuting paraan ay ang paggamit double-checked locking (nababababa sa ibaba), ngunit kahit ang dibuhong iyon ay may mga patibong kung hindi tama ang pagkakatupad.
4.
Ang synchronization ay may maraming anyo: pamamaraan, blocks, , , , at iba pa. over-synchronization ⁇ apply roast-grading barollow-gined locks kapag ang pinong-gined control ay makukuha recrucledences sa hindi kinakailangang pagtatalo. Sa ilang mga aplikasyon (e.g., ang mga sistemang real-time na may mahigpit na adytrys kahit na badyet na may ilang mga sub-gor na staintentrance kahit na ang isang daangnoid na puntos ay maaaring maging hindi pa rin ang mga sekwensiyalment na sekwensiyalment na stadong sekwed na sekswal na sekswal.
5.[Ignog ang [volatile Teyword
Sa mga wikang katulad ng Java, C#, at C++ (na may ), ang ⁇ volatile ⁇ ] ⁇ ang susing salita (o katumbas) ay mahalaga para sa tamang pagkakatanaw sa kodigong multi-threading. Kung wala ito, ang tagatipon o CPU ay maaaring mag-ayos ng mga instruksiyon, at ang mga pagbabagong ginawa ng isang sinulid ay maaaring hindi makita ng isa pa. Sa double-cheed locking, ang hindi pag-aprogham ay maaaring maghayag ng isang halimbawa bilang ang CPU.[T] Ang isang hindi inaasahang pagkakamali ay maaaring gumawa ng isang hindi inaasahan.[T] Ang isang hindi inaasahang pangyayari ay maaaring mangyari.
Pinakamabuting Gawain Para sa Tread-ligtas na Pag - iisa
Para maiwasan ang mga ito, sundin ang mga napatunayang estratehiya — ang bawat paraan ay may kinalaman sa ligtas na paggawa, at pagiging simple.
Pribadong Pagtatayo at Pag - iingat ng Statiko
Anuman ang paraan ng pag - aayos sa unang pagkakataon, dapat na pribado ang tagapagtayo. Ang halimbawang ito ay dapat na itago sa isang static field.
Gumamit ng Synchronized Blocks Tanging Kung Kailangan
Para sa tamad na pag-uumpisa, ang double-checked na locking pattern ay nagpapaliit ng integral na integrasyon sa itaas:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
Singleton result = instance; // Local variable for performance
if (result == null) {
synchronized (Singleton.class) {
result = instance;
if (result == null) {
instance = result = new Singleton();
}
}
}
return result;
}
}
Sa kodigong ito, ang tseke sa labas ng complementing block ay umiiwas sa lock sa itaas kapag umiiral na ang pagkakataon.Ang panloob na tseke ay tumitiyak na isang sinulid lamang ang lumilikha ng pangyayari. Ang susing salita ay pumipigil sa pagtuturo na muling ayusin at tinitiyak na ang atas ay lubusang nakikita ng ibang sinulid.[T] Pansinin na ating inaayos ang pagkakataon sa isang lokal na pagbabago para sa pagganap. Ang huwarang ito ay tama sa Java+ 5 (may tamang memorya) at mga gawang katulad ng C&T] at may kasamang C&T] sa pag-alaala (−18 C.
Sabik na Unang Pag - aasawa
Kung ang isangton ay laging kailangan at ang paglikha ay mura, ang sabik na pag-iisyu ay ang pinakasimpleng sinulid-ligtas na paglapit:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
Ang pagkarga ng klase ay likas na kasabay ng JVM, kaya walang karagdagang koordinasyon ang kinakailangan. Gayunpaman, ito ay lumilikha ng pagkakataon sa oras ng pagkarga ng klase, na maaaring hindi kanais-nais sa mga sistemang mapagkukunan-contrained o kapag ang isangton ay nakasalalay sa runtime configuration na hindi pa makukuha.
Static Holder Ediment (Intitialization-on-demand)
Ang disenyong ito ay nagsasama ng tamad na panimulang salita at ng ligtas na sinulid nang walang maliwanag na pagdurugtong:
public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
Ang klase ay nakakarga lamang kapag ang unang tawag, at ang JVM ay gumagarantiya ng ligtas na paglalathala ng static field sa panahon ng pagkarga ng klase. ito ay malawak na itinuturing bilang pinaka-eleganteng solusyon para sa Java singletons.
Enum-Based Singleton (Java)
Joshua Blochives [[Effective Java][Talaksan] na gumamit ng enum:
public enum Singleton {
INSTANCE;
// methods and fields
}
Ang mga enum constant ay ganap na , at ang wikang Java ay gumagarantiya na ang mga enum na mga pagkakataon ay nalilikha lamang ng isang beses, kahit na sa ilalim ng serialization o repleksiyon at parehong sinulid-ligtas at maikli ngunit malaman. Gayunpaman, ang mga enum ay hindi maaaring magpalawig ng mga klase (nagpapatupad lamang ng mga interface), kaya hindi sila angkop para sa lahat ng mga ginagamit na kaso.
Equivalent Pattern in C++ at C#
Sa C++, ang Meyerites Sington (local static premition) ay sinulid-ligtas mula noong C+++11:
Singleton& getInstance() {
static Singleton instance;
return instance;
}
Sa C#, ang klase ay nagbibigay ng isang de-pack-in thread-ligtas na tamad na paunang pag-uuna:
public class Singleton {
private static readonly Lazy<Singleton> _lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance => _lazy.Value;
}
Pagsubok at Pagpapakundangan sa mga Aparato ng Inhinyeriya
Sa mga aplikasyon sa inhinyeriya, ang huwarang pang-isahangton ay kadalasang nangangasiwa sa kabahaging mga yaman katulad ng mga drayber ng hardware, mga setting, mga pool ng sinulid, o mga serbisyo ng pagtotroso. ang pagsubok sa gayong mga singleton sa mga pagsubok na multi-treaded ay nangangailangan ng maingat na disenyo. Isaalang-alang ang mga sumusunod:
- Gumawa ng mga paisahang tons testable sa pamamagitan ng paglalaan ng paraan upang maiayos ang pangyayari (hal.g., isang protektadong paraan na ginagamit lamang sa mga pagsubok) o sa inkorsyon ng mga dependensiya sa pamamagitan ng isang interface. Maraming mga modernong aplikasyon ang lubusang umiiwas sa mga solongtons pabor sa mga balangkas ng independence injection na nagpapatakbo ng lifecycle.
- Performance profilling sa mga sistemang real-time o high-frequency: sukatin ang ibabaw ng kompleksidad.[kailangan ng sanggunian] Sa ilang kaso, maaaring bigyang-katwiran ang isang lock-free singleton gamit ang (C#) o (C++).
- [[kailangan ng isahangton] upang maging natatangi kada proseso, hindi sa ibayo ng mga proseso. kung kailangan mo ng isang cluster-wide singleton, gumamit ng panlabas na koordinasyon (e.g., isang database, Zoo Keeper, o leader election).
- Ang repleksiyon at serialization ay maaaring mag-iba ng mga singleton. Gamitin sa Java serialization, at iwasan ang replective instantiation sa pamamagitan ng paghahagis ng eksepsiyon sa konstruksyon kung ay itinakda na.
Pagsasaayos
Ang disenyong Singleton ay nananatiling isang mahalagang kasangkapan sa software engineerivis toolbox, ngunit ang pagpapatupad nito sa mga kapaligirang multi-threaded ay nangangailangan ng mahigpit na pansin sa detalye. Sa pag-unawa at pag-iwas sa mga karaniwang pagkakamali na gaya ng mga non-private na mga standing computing, missing computation, di-tamang paggamit, at mga over-synchronization na mga adroveleration oneton. Ang double-checked na locking patter, stamplord, at enum-bandton sa bawat Java ay maaaring mag-based sa isang matatag na balanse at kahusayan sa prekweeksing pang-elekweeksyon ng mga prekto at mga modernong C+#, at mga katangiangor.
Para sa higit pang pag - aaral, tingnan ang sumusunod na mga pantulong:
- Wikipedia: Singleton Circle]
- ] Oracle Java Singleton Tutorial
- Ang "Double-Checked Locking ay Binigkas" Pagpapahayag
- Microsoft .NET Singleton Circle
Sa wakas, ang pinakamahusay na iisang - klasipikasyon ang pinakasimple sa iyong mga kahilingan. Kapag nag - aalinlangan, mas gusto mong maunang - salita o ang disenyong static bearer, at laging magsulat ng mga constant unit test para patunayan ang pagiging tama sa ilalim ng pagtatalo.