Sarhoşken yaptığınız hangi eylemlerden çok utanıyorsunuz? Panik Bozuklukları Performans Testi Sonuçları

KALP NEVROZU (KARDİYOFOBİ). Panik sendromuyla birlikte özel bir fobi türü, özellikle karakteristik klinik tablosu ve belirgin sıklığı nedeniyle tanımlanması gereken kardiyofobidir. Çoğunlukla gençlerde, daha çok erkeklerde ve çocuklarda görülür.

Paroksismal kaygı durumları Hastaların, kalbin duracağından ve öleceğinden korktuğu kalp krizi, bedensel bir hastalık olmadan da ortaya çıkabiliyor. Bir sonraki atağın başlangıcında mide bulantısı, baş dönmesi, içsel kaygı ve kalpte hafif bir sıkışma ortaya çıkar.

Ancak çoğu durumda herhangi bir uyarı olmaksızın ciddi bir saldırı meydana gelir: çarpıntı vücutta hissedilir, bir miktar artış olur tansiyon, kalp bölgesinde ağır bir baskı ve gerginlik hissi, hava eksikliği, terleme, baş dönmesi ve bayılma hissi (ancak bilinç kaybı değil), tüm vücutta titreme ve temel korku. Hasta bir anda kalbinin duracağını ve düşüp öleceğini zanneder. Bu, kendini yok etme ve ölüm korkusudur. Şu tarihte: güçlü heyecan hastalar koşuyor ve yardım için yalvarıyorlar. Arabada yolculuk yaparken korku krizi yaşanırsa hasta durup mola vermek zorunda kalır.

İlk atak sonrasında fobik gelişim meydana gelir. Hastalar zihinsel dengelerini kaybederler, sürekli korku içinde yaşarlar, bir sonraki saldırıyı veya ölümü beklerler, korku korkusu (beklenme korkusu, fobi) yaşarlar. Aynı zamanda terapistin mesajı da onlara yardımcı olmuyor. normal göstergeler kalp fonksiyonu ya da önceki saldırıların hiçbir sonucu olmadığına dair ikna. Atakların sıklığı ve aralarındaki aralıklar düzensizdir. Hasta aralıklarla kalp fonksiyonlarını dikkatle izler, nabzını kontrol eder ve en ufak sapmaları kaydeder. Rastgele ekstrasistolleri, umutsuz sonucu olan bir hastalığın tartışılmaz belirtileri olarak algılıyor.

Hastalar diğer bitkisel belirtilerin yanı sıra sağlık durumlarındaki hafif dalgalanmaları da dikkatle gözlemlerler. Hastalar kendilerine bakarlar, yürümeye cesaret edemezler, bir atağı önlemek için her türlü stresi, endişeyi ve her şeyden önce zor durumları ortadan kaldırmaya çalışırlar (kaçınma davranışı). Ölüm korkusunun yerine, giderek artan bir şekilde korku ve korku uyandıran durumların korkusu ortaya çıkıyor.

GÖRÜNÜŞ KOŞULLARI. İlk kardiyofobik atağın nedeni genellikle akut bir çatışma ve aşırı gerginlik, ayrılık ve hayal kırıklığı, yalnızlık ve terk edilme durumu ve yakın birinin kalpten ölümü durumunda kaygıdır.

Genç ve sağlıklı kişilerde bile kalpten ölümün her zaman olabileceğini bilmek endişe verici bir faktör haline geliyor. Yoğun kahve ve nikotin tüketimi bu süreci tetikleyebilir. Başlangıç ​​genellikle çocukluktan gelir. Çoğunlukla şımarık ve bağımlı çocuklar, anneye belirgin bir bağımlılıkla, büyük ölçüde kararsız tutumlarla etkilenirler: bir yanda sevgi beklentisi, diğer yanda saldırgan dürtülerle bağımsızlık arzusu, diğer yanda bağlanma ve bağlanmaya dair çelişkili fanteziler. ayrılma. Bu tür tutumlar özellikle bağlantıların koptuğu, ayrılıkların ve hayal kırıklıklarının yaşandığı durumlarda tehlikelidir. Kardiyofobi, ayrılık korkusunu, bunu istediğinin ve ondan korktuğunun farkına varmadan yaşar. Ebeveynlerle ortak sorunlar ve ortaklarla çatışmalar düzenli olarak ortaya çıkar.

TEDAVİ
Eğer içindeyse akut durum Bir doktorun varlığı ve onunla konuşmak iyileşmeye neden olmaz, sakinleştiriciler veya beta blokerler belirtilir. Korkulu nevrozlu diğer hastalar gibi, birçok fobik de alkolle kendi kendine ilaç tedavisine çalışır; ancak etkisi yetersizdir ve alkole bağımlı hale gelme tehlikesi büyüktür. Farmakoterapi, öncelikle akut vakalarda ve başlangıçtaki vakalarda yalnızca yardımcı bir tedavi yöntemidir. etkili çözüm.

Psikoterapi belirleyicidir. Ne kadar erken başlarsa o kadar iyi. Nedenlerini incelemek ve çatışma durumlarıİlk kardiyofobik ataklardan hemen sonra, sonraki fobik gelişimi durdurabilir. Daha sonraki tedaviler daha zordur ve uzun süreli psikoterapi gerektirir.

Bunlar ve diğer anksiyete bozuklukları için davranışsal terapi (uyarılmayla yüzleşme, bilişsel terapi, kendine güven eğitimi) özellikle endikedir. Kaygıdan kaçınma eğitiminin ayırt edici bir özelliği, duyarsızlaştırma modeli (günlük durumların karşılık gelen koşullarına) üzerinde çalışması ve kaygı yönetimi eğitiminin, fobik bir duruma (sel) zorla dalmayı ve başa çıkma stratejilerinin oluşturulmasını kullanmasıdır. Şiddetli anksiyete bozuklukları için yapılması gerekenler klinik tedaviÇeşitli psikoterapi modellerinin kullanılması.


02.10.2011, 21:27

Bir adamı dövdüğü ve tişörtünü ağaca astığı için, aptal adamı tek başına birkaç kilometre kovaladı ve adam düştüğünde üzerine işemeye başladı ama bunu hak ettiler.

Büyük bir şirkette bir kızı rahatsız ettim ve erkek arkadaşının onu indirimden aldığını ve aynı zamanda muz yediğini ve kabuklarını minibüste herkesin kucağına koyduğunu söyledim, ayrıca eteklerin altına baktığımda sürekli barlarda lezbiyen gösterileri düzenliyorum. VIP klüpteki garsonların yorumlarını yaptım ama genel olarak çok sarhoşum İnsanların uyanırsan utanırsın demesini sevdiğimi hemen unutuyorum ama tam olarak neden benim hakkımda olduğunu hatırlamıyorum

Son sarhoşluktan sonra bıktım:
1. balkondan adama "beni em" diye bağırdı
2. sigara yedim
3.elma fırlattım
4. Adamı aradım ve ona kaba bir şekilde seks yapmayacağımı söyledim
5. Greyfurt suyunda boğaları boğmak
6. Annemi arayıp ayık olduğumu söyledi
7. Arkadaşımın erkek arkadaşından bize biraz şarap getirmesini istedim.
8. Tuvaletin önünden işedim çünkü 2 tane vardı - yanlış olanı seçtim ve sonra düştüm
9. banyodan düştüm

Bir keresinde birkaç bardak şampanya içmiş olmama rağmen elimde bıçakla kocamın peşinden koşmuştum. Ertesi sabah korktum; ya ona bıçakla vurursam, ama onu korkutmaya karar verdim. Ve neden bu kadar tekme yediğimi bilmiyorum!

Hep aynı şey; sarhoş olduğumda parka gidip onlarla dalga geçecek zavallıları arıyorum ya da forumda bu konuları açıyorum... sabahları düşünüyorum, aptal mıyım?...

Bir keresinde bir adam bana asılmıştı ve ben o kadar sarhoştum ki ona hiçbir şeyin ters gitmeyeceğini, çünkü ben "Kanlı Mary"ydim (onlar öyleydi) ve bu lakap ruhuma o kadar işlemişti ki neredeyse Tanıştığım herkese bağırdım: “Ben Bloody Mary”, çok şükür benim memleketimde değildi

-* eski sevgilimi aradım, onun hakkında düşündüğüm her şeyi anlattım
*Sevgilimi aradım, onu ne kadar istediğimi söyledim
*folyoyla shawarma yedim
* bana yardım etmesine ve bana su getirmesine rağmen kulüpte tanıştığım bir adama küfrettim
*bir kulüpte düzenlenen yarışmada striptiz dansı yaptı, ikinci oldu
*bir yabancıya buz fırlattı
*erkeğimin arkadaşı sarı bir Hummer kullanıyor. Kore'de hiç böyle bir şey görmemiştim. hep birlikte partiye gittiğimizde. Adamımın arabasından eğildim ve önümüzde giden Hummer'ı işaret ederek bu arabanın arkadaşım olduğunu bağırdım.
*Dün kulüpteydim. Sabah taksiyle eve dönerken şoföre şunu söyledim: [Koreceden çeviri. kelimesi kelimesine!] “Yediğim yemek bana dışarı çıkmak istediğini söyledi!”
*Benim de Moğol bir arkadaşım var. Sırtına tırmandım, beni sırtında taşımaya zorladım ve bütün sokağa onun benim Moğol atım olduğunu bağırdım.
ama genel olarak çok daha fazlası vardı, hatırlamayacaksınız...

Adama sabah saat 4’te yazdım” İyi geceler, Masraflı"

Arkadaşlarım ve ben konyak içip sarhoş olduk, herkes eve gitti ve ben aptalca bir taksi çağırdım (saat sabahın 3'üydü) ve 4 ay önce ayrıldığım eski erkek arkadaşımı görmeye gittim (arkadaş kaldık). Girişe nasıl girdiğimi, dairesine nasıl girdiğimi, kapısını kırıp “BENİMLE EVLEN MARAT” diye bağırdığımı hatırlamıyorum, zavallı şey delirdi, beni eve sürükledi ve soğuk bir duşa soktu, bana demli çay verdi 2 saat sonra ayrıldım ve ne yaptığımı anladığımda GERÇEKTEN UTANDIM.Sonra barıştık ve hala birlikteyiz. Bundan sonra bir kadeh daha şampanya içmeyeceğim.


...

02.10.2011, 22:09

Öldürülen kadın bir adamla bahçede yürüyordu ve sonra bana öyle geldi ki adam yanımda değil birkaç adım önümde yürüyerek beni bir şekilde rahatsız etti. Sinirlendim ve bir ağaca tırmandım ama o farketmedi bile... bahçede bir buçuk saat koştu beni aradı... ve ben sakince ağacın üzerinde kendimden geçtim ve sabaha kadar uyudum. ...
...
Ancak sabah dallara nasıl geldiğimi hemen hatırlayamadım. Allah kahretsin sonrası nasıldı
;D;D;D

Tercüme

02.10.2011, 22:42

Ayıkken yapılan bazı eylemlerden utanıyorum :) Ama bu felsefeye daha yakın. Sarhoşken... pek çok şey eğlenceliydi, utanç vericiydi... hayır, üzgünüm))))

Elena Lotus

02.10.2011, 23:17

Dün, telefonumun (OOO!!!) artık bana ait olmadığını anlayınca çok sarhoş oldum ve (kim bilir beni fare gibi içtiğimi söylemeyin) sonra bir şey yaptım... sadece yakın arkadaşlarıma, genel olarak sır ve sonra kime anlatacağımı düşünürüm... Paberti restoranı yine şok oldu.Şimdi ne olduğunu görmek umuduyla fotoğraf galerisine bakıyorum: (ama ben 'Utanmıyorum... hayır... Sadece terbiyeli olduğumu düşündüm.

02.10.2011, 23:31

;D;D;D
Teyzelerin içki içmemesi gerektiğini her zaman savundum!!! HERKES!!!;)

..;D;D;D doğruyu söylüyorsun

02.10.2011, 23:36

Sarhoş bir kadın Çin kuş tüyü ceketine benzer: yumuşak ve tam oturur.
Galygin

Elena Lotus

02.10.2011, 23:41

Ama erkekler evet sever mi?Herkes içebilir. teyzeler ve amcalar...sadece dikkatli olmanız gerekiyor...bugün başınız ağrımıyor...ruhunuz acıyor...bir içki içer misiniz?Bu sadece bir kısır döngü;)

03.10.2011, 00:15

Genç ve sağlıklıyken her şeyi ve her şeyi tüketin :)

03.10.2011, 01:48

kadın forumundan seçici olarak çalındı ​​:)

Neredeyse annemin önünde çamaşır sepetine işiyordum..... tuvaletle karıştırıyordum.... ayy....

Öldürülen kadın bir adamla bahçede yürüyordu ve sonra bana öyle geldi ki adam yanımda değil birkaç adım önümde yürüyerek beni bir şekilde rahatsız etti. Sinirlendim ve bir ağaca tırmandım ama o farketmedi bile... bahçede bir buçuk saat koştu beni aradı... ve ben sakince ağacın üzerinde kendimden geçtim ve sabaha kadar uyudum. ...
...
Ancak sabah dallara nasıl geldiğimi hemen hatırlayamadım. Allah kahretsin sonrası nasıldı

Balkonda annemin soğan yetiştirdiği leğen ve saksılar vardı.Bu saksıların her birine “zayıf” işedim =((((kendi yataklarıma ((elbette anneme söylemeyeceğim, her şeyi içine atacağım) çöp, buradayım, yeşilliklerine işemeye karar verdim, büyümeye devam etti, sonra salataya gitti

03.10.2011, 05:35

Arkadaşlarım ve ben konyak içip sarhoş olduk, herkes eve gitti ve ben aptalca bir taksi çağırdım (saat sabahın 3'üydü) ve 4 ay önce ayrıldığım eski erkek arkadaşımı görmeye gittim (arkadaş kaldık). Girişe nasıl girdiğimi, dairesine nasıl girdiğimi, kapısını kırıp “BENİMLE EVLEN MARAT” diye bağırdığımı hatırlamıyorum, zavallı şey delirdi, beni eve sürükledi ve soğuk bir duşa soktu, bana demli çay verdi 2 saat sonra ayrıldım ve ne yaptığımı anladığımda GERÇEKTEN UTANDIM.Sonra barıştık ve hala birlikteyiz. Bundan sonra bir kadeh daha şampanya içmeyeceğim.

Bu oldukça gerçek hikaye Aşk.
Ve içmenin yararları hakkında da.

(İçki, kızlar ve mutluluk size gelecektir.)

PHP'de çoklu iş parçacıklarını taklit etmek için internette dolaşan pek çok çözüm var. Çoğu zaman çatallara dayanırlar, ancak temanın curl, proc_open vb. kullanan varyasyonları da vardır.

Karşıma çıkan tüm seçenekler şu ya da bu nedenle bana uymadı ve kendi çözümümü yazmak zorunda kaldım.
Aşağıdaki gereksinimlere sahiptim:

  • Çatal kullanımı;
  • Gerekli uzantıların yokluğunda arayüzün korunduğu senkronize mod;
  • Alt süreçlerin yeniden kullanımı;
  • Süreçler arasında tam veri alışverişi. Onlar. argümanlarla çalıştırın ve bittiğinde sonucu alın;
  • Operasyon sırasında bir alt "iş parçacığı" süreci ile ana süreç arasında olay alışverişi yapma yeteneği;
  • Yeniden kullanımı sürdürürken, argümanları aktarırken ve sonuç alırken bir iş parçacığı havuzuyla çalışmak;
  • Çalışma zamanı hatalarının işlenmesi;
  • İşin gerçekleştirilmesi için zaman aşımları, bir iş parçacığının çalışmasını beklemek, başlatma;
  • Maksimum performans;
Sonuç bir kütüphanedir AzaThread(eski adı - CThread).

Sabırsız olanlar için kaynağın linki:
github.com/Anizoptera/AzaThread

Tanım

AzaThread, iş parçacığı sınıfları oluşturmak için basit bir arayüz sağlar. Aslında eşzamansız olarak çalışmak için ayrı süreçler kullanırlar, ancak bunu umursamamalısınız. Bir iş parçacığından olaylar gönderebilir, sonuçları döndürebilir, bir iş parçacığını birçok kez ona başlatma argümanlarını ileterek kullanabilir veya işin farklı şekillerde gerçekleştiğine dikkat etmeden, sıcak kek gibi görevlerinizi sıralayan 16 iş parçacığından oluşan bir havuz oluşturabilirsiniz. süreçler.

Ayrıca, yapılandırmanız için özel olarak optimum iş parçacığı sayısını ve işlemler arasında veri aktarma seçeneğini seçerek kitaplığın performansını farklı modlarda kolayca test edebilirsiniz.

Tam çalışma için aşağıdaki uzantılar gereklidir: özgür ruhlu, posix Ve pcntl.

Kitaplık, işlemler arasındaki iletişim için LibEvent ve eşleştirilmiş yuvaları kullanır. Verileri (argümanlar, sonuçlar ve olay verileri) aktarmak için 5 seçeneği destekler!

Seçenekleri anında performans verileriyle sunuyorum. Intel Core i7 2600K 3.40 Ghz'de (bir VMware sanal makinesinde Ubuntu 11.04) sekiz iş parçacığından oluşan bir havuzla test edilmiştir. Testin 10 tekrarı için ortalama sonuçlar jps cinsinden verilmiştir (saniyedeki iş sayısı - yalnızca argümanları alan ve saniyede veri gönderen görevlerin sayısı).

Soketlerle çalışmaya yönelik uzantı otomatik olarak seçilir. Varsa uzantı kullanılır prizler Bu da gelişmiş performans sağlar. Aksi takdirde kullanılacaktır aktarım.

Çocuk süreç mevcut tüm sinyalleri dinler. Varsayılan olarak tümünün (SIGWINCH ve SIGINFO hariç) ardından kapatma gelir. Ancak iş parçacığı sınıfında sinyalin adını taşıyan bir yöntem oluşturularak bu kolayca geçersiz kılınabilir. Örneğin sigVinç.

Ana süreçte tüm sinyaller de varsayılan olarak durdurulur. Bu, sınıf parametresi ayarlanarak değiştirilebilir listenMasterSignals yanlış yapmak. Bu durumda yalnızca SIGCHLD işlenecektir. adlı statik bir yöntem oluşturarak kendi işleyicilerinizi kolayca ekleyebilirsiniz. M< имя сигнала > . Örneğin mSigTerm.

Bir alt süreç herhangi bir nedenle ölürse, yeni bir görev başlatıldığında sınıf otomatik olarak çatallanır. Bu fark edilmeden gerçekleşir ve bunun hakkında hiç düşünmenize gerek yoktur. Herhangi bir hata durumunda örneğin yeniden oluşturulmasına gerek yoktur.

Çocuk süreç periyodik olarak ana sürecin varlığını kontrol eder. Aniden ölürse çocuk otomatik olarak sona erecektir.

Bir iş parçacığı veya iş parçacığı havuzu tarafından kullanılan tüm kaynaklar, yıkıcı çağrıldığında otomatik olarak temizlenir. Ancak yöntemi çağırarak zorla temizlenebilirler. Temizlemek. Bu durumda iş parçacığı/havuz artık kullanılamaz.

Şu tarihte: standart ayarlar iş parçacığı, sınıf oluşturulduğunda hemen önceden başlatılır. Parametreyi ayarlarsanız ön çatal false ise çatallanma yalnızca görev başlatıldığı anda gerçekleşir.

Genel olarak, oldukça fazla sayıda özelleştirilebilir parametre vardır. Çataldan sonra alt sürecin adının değiştirilmesi (parametre pİsim yapıcı), görev süresi boyunca zaman aşımı ( zaman aşımıÇalışma), bir alt sürecin görevleri bekleyebileceği maksimum süre için zaman aşımı ( zaman aşımıMaxWait), ön başlatma süresi için zaman aşımı ( zaman aşımı başlatma), soket okuma arabellek boyutları ( pipeReadSize, pipeMasterReadSize).
İş parçacıkları için çoklu görev modunu devre dışı bırakabilirsiniz ( çoklu görev). Bu durumda, görev her tamamlandığında alt süreç ölecek ve bir sonraki başlatma için yeniden çatallanacaktır. Bu, performansı gözle görülür şekilde azaltacaktır.

Kod testlerle kaplıdır ve ayrıntılı olarak belgelenmiştir; kullanım örnekleri dosyada görüntülenebilir ve çalıştırılabilir. örnek.php.
Daha karmaşık örnekler hata yönetimi ünite test kodunda görülebilir.

Çok fazla hata ayıklama modu var detaylı bilgi tam olarak ne olduğu ve nerede olduğu hakkında.

Kullanma örnekleri

Ana özellik maksimum basitliktir. Bir şeyi yalnızca ayrı bir "iş parçacığında" çalıştırmak istiyorsanız aşağıdaki kod yeterlidir:
class exampleThread, Thread'i genişletir ( korumalı işlev proses() ( // Bazıları burada çalışır ) ) $thread = new exampleThread(); $thread->bekle()->çalıştır();
Tam teşekküllü çalışma için gereken her şey varsa, görev eşzamansız olarak tamamlanacaktır. Değilse, o zaman her şey çalışmaya devam edecek, ancak senkronize modda.

Bir parametre ileterek ve sonucu alarak kod biraz daha karmaşık görünecektir:
class SampleThread Thread'i genişletir ( korumalı işlev proses() ( return $this->getParam(0); ) ) $thread = new exampleThread(); $thread->bekle()->çalıştır(123); $sonuç = $thread->wait()->getResult();

Benzer şekilde, hafif bir el hareketiyle akıştan olay işlemeyi ekliyoruz:
class exampleThread Thread'i genişletir ( const EV_PROCESS = "process"; protected function proses() ( $events = $this->getParam(0); for ($i = 0; $i)< $events; $i++) { $event_data = $i; $this->tetikleyici(self::EV_PROCESS, $olay_verisi); )) ) ) // Ek argüman. $ekArgüman = 123; $thread->bind(ExampleThread::EV_PROCESS, function($olay_adı, $olay_verisi, $ek_arg) ( // olay işleme), $additionalArgument); $olaylar = 10; // iş parçacığının oluşturacağı olayların sayısı // İlk çağrıdan önce iş parçacığını manuel olarak beklemekten kaçınmak için, // alt sınıftan $thread->wait(); preforkWait özelliğini TRUE olarak geçersiz kılabilirsiniz; $iş parçacığı = yeni ÖrnekThread(); $thread->run($olaylar)->bekle();

Ve son olarak, çalışma zamanı hata işleme ile sekiz iş parçacığından oluşan bir havuz kullanarak:
$threads = 8 // Thread sayısı $pool = new ThreadPool("ExampleThread", $threads); $sayı = 25; // Görev sayısı $sol = $sayı; // Kalan görev sayısı ( // Havuzda boş iş parçacıkları varsa // Ve hala yürütülecek görevlerimiz var while ($pool->hasWaiting() && $left > 0) ( // Başlarken şunu alırız: iş parçacığı kimliği $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( / / Görev başarıyla tamamlandı // Sonuç, // iş parçacığı kimliği ($threadId) $num--; ) ) if ($failed) ( // Yürütme hatalarını yönet. // İşin başarısız bir şekilde tamamlandığı kabul edilir // alt süreç yürütme sırasında öldüyse veya // görev yürütme için zaman aşımı dolduysa foreach ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Tüm alt süreçleri sonlandır. Havuzun kullandığı kaynakları temizliyoruz. $havuz->temizleme();

Performans Testi Sonuçları

Testleri Ubuntu 11.04 yüklü iki makinede yaptım.
Bunlardan ilki Intel Core i3 540 3.07 Ghz
İkincisi Intel Core i7 2600K 3.40 Ghz (Ubuntu, VMware sanal makinesinde çalışır)

Verimlilik artışını değerlendirebilmeniz için sonuçları basit bir şekilde sunuyorum.
Yine, bunlar jps cinsinden 10 test tekrarı serisinin ortalama sonuçlarıdır (saniye başına iş - saniye başına görev sayısı).

Bir görev olarak iş parçacıkları aşağıdaki çöpleri gerçekleştirir:
için ($i = 0; $i< 1000; $i++) { $r = mt_rand(0, PHP_INT_MAX) * mt_rand(0, PHP_INT_MAX); }
İlk sonuç senkron çalışma modu (çatalsız) için gösterilir.
İlk konfigürasyonda 18 ve 20 iş parçacığını denemedim çünkü 12 iş parçacığında performans düşmeye başladı.

Konu sayısı İlk konfigürasyon Saniye
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

Yani işlemciye bağlı olarak performans 2-4 kat veya daha fazla artar!

Gerekli parametrelerle bir dizi testi çalıştıran kod dosyadadır. örnekler/speed_test.php. Böylece performansı kolayca test edebilir ve kendiniz için en uygun iş parçacığı sayısını seçebilirsiniz.

PHP'de çoklu iş parçacıklarını taklit etmek için internette dolaşan pek çok çözüm var. Çoğu zaman çatallara dayanırlar, ancak temanın kullanımında da farklılıklar vardır. kıvırmak, proc_open ve benzeri.

Karşıma çıkan tüm seçenekler şu ya da bu nedenle bana uymadı ve kendi çözümümü yazmak zorunda kaldım. Aşağıdaki gereksinimlere sahiptim:

  • Çatal kullanımı;
  • Gerekli uzantıların yokluğunda arayüzün korunduğu senkronize mod;
  • Alt süreçlerin yeniden kullanımı;
  • Süreçler arasında tam veri alışverişi. Onlar. argümanlarla çalıştırın ve bittiğinde sonucu alın;
  • Operasyon sırasında bir alt "iş parçacığı" süreci ile ana süreç arasında olay alışverişi yapma yeteneği;
  • Yeniden kullanımı sürdürürken, argümanları aktarırken ve sonuç alırken bir iş parçacığı havuzuyla çalışmak;
  • Çalışma zamanı hatalarının işlenmesi;
  • İşin gerçekleştirilmesi için zaman aşımları, bir iş parçacığının çalışmasını beklemek, başlatma;
  • Maksimum performans.

Sonuç, AzaThread kitaplığıydı (eski adıyla CThread).

Tanım

AzaThread, iş parçacığı sınıfları oluşturmak için basit bir arayüz sağlar. Aslında eşzamansız olarak çalışmak için ayrı süreçler kullanırlar, ancak bunu umursamamalısınız. İşin devam ettiği gerçeğine hiç dikkat etmeden, bir iş parçacığından olaylar gönderebilir, sonuçları döndürebilir, tek bir iş parçacığını birden çok kez kullanabilir, başlangıç ​​argümanlarını iletebilir veya sıcak kek gibi görevlerinizi sıralayan 16 iş parçacığından oluşan bir havuz oluşturabilirsiniz. farklı süreçlerde.

Ayrıca, yapılandırmanız için özel olarak optimum iş parçacığı sayısını ve işlemler arasında veri aktarma seçeneğini seçerek kitaplığın performansını farklı modlarda kolayca test edebilirsiniz.

Tam çalışma için aşağıdaki uzantılar gereklidir: özgür ruhlu, posix Ve pcntl.

Kitaplık, işlemler arasındaki iletişim için LibEvent ve eşleştirilmiş yuvaları kullanır. Verileri (argümanlar, sonuçlar ve olay verileri) aktarmak için 5 seçeneği destekler!

Seçenekleri anında performans verileriyle sunuyorum. Intel Core i7 2600K 3.40 Ghz'de (bir VMware sanal makinesinde Ubuntu 11.04) sekiz iş parçacığından oluşan bir havuzla test edilmiştir. Testin 10 tekrarı için ortalama sonuçlar jps cinsinden verilmiştir (saniyedeki iş sayısı - yalnızca argümanları alan ve saniyede veri gönderen görevlerin sayısı).

Soketlerle çalışmaya yönelik uzantı otomatik olarak seçilir. Varsa uzantı kullanılır prizler Bu da gelişmiş performans sağlar. Aksi takdirde kullanılacaktır aktarım.

Çocuk süreç mevcut tüm sinyalleri dinler. Varsayılan olarak tümünün (SIGWINCH ve SIGINFO hariç) ardından kapatma gelir. Ancak iş parçacığı sınıfında sinyalin adını taşıyan bir yöntem oluşturularak bu kolayca geçersiz kılınabilir. Örneğin sigWinch.

Ana süreçte tüm sinyaller de varsayılan olarak durdurulur. Bu, listenMasterSignals sınıf parametresini false olarak ayarlayarak değiştirilebilir. Bu durumda yalnızca SIGCHLD işlenecektir. m adında statik bir yöntem oluşturarak kendi işleyicilerinizi kolayca ekleyebilirsiniz.<имя сигнала>. Örneğin, mSigTerm.

Bir alt süreç herhangi bir nedenle ölürse, yeni bir görev başlatıldığında sınıf otomatik olarak çatallanır. Bu fark edilmeden gerçekleşir ve bunun hakkında hiç düşünmenize gerek yoktur. Herhangi bir hata durumunda örneğin yeniden oluşturulmasına gerek yoktur.

Çocuk süreç periyodik olarak ana sürecin varlığını kontrol eder. Aniden ölürse çocuk otomatik olarak sona erecektir.

Bir iş parçacığı veya iş parçacığı havuzu tarafından kullanılan tüm kaynaklar, yıkıcı çağrıldığında otomatik olarak temizlenir. Ancak temizleme yöntemini çağırarak zorla temizlenebilirler. Bu durumda iş parçacığı/havuz artık kullanılamaz.

Standart ayarlarla iş parçacığı, sınıf oluşturulduğunda hemen önceden başlatılır. Prefork parametresini false olarak ayarlarsanız çatal yalnızca görev başlatıldığı anda gerçekleşir.

Genel olarak, oldukça fazla sayıda özelleştirilebilir parametre vardır. Çataldan sonra alt sürecin adının değiştirilmesi (yapıcının pName parametresi), görev yürütme süresi boyunca zaman aşımı (timeoutWork), alt sürecin görevler için beklediği maksimum süre için zaman aşımı (timeoutMaxWait), ön-işlem için zaman aşımı başlatma süresi (timeoutInit), yuvaları okumak için arabelleklerin boyutu (pipeReadSize, pipeMasterReadSize). İş parçacıkları için çoklu görev modunu devre dışı bırakabilirsiniz (çoklu görev). Bu durumda, görev her tamamlandığında alt süreç ölecek ve bir sonraki başlatma için yeniden çatallanacaktır. Bu, performansı gözle görülür şekilde azaltacaktır.

Kod testlerle kaplıdır ve ayrıntılı olarak belgelenmiştir; kullanım örnekleri example.php dosyasında görüntülenebilir ve çalıştırılabilir. Hata işlemeyle ilgili daha karmaşık örnekler ünite test kodunda görülebilir.

Tam olarak ne olduğu ve nerede olduğu hakkında çok ayrıntılı bilgiler görüntüleyen bir hata ayıklama modu vardır.

Kullanma örnekleri

Ana özellik maksimum basitliktir. Bir şeyi ayrı bir "iş parçacığında" çalıştırmak istiyorsanız aşağıdaki kod yeterlidir:

Class SampleThread, Thread'i genişletir ( korumalı işlev proses() ( // Bazıları burada çalışır ) ) $thread = new exampleThread(); $thread->bekle()->çalıştır();

Tam teşekküllü çalışma için gereken her şey varsa, görev eşzamansız olarak tamamlanacaktır. Değilse, o zaman her şey çalışmaya devam edecek, ancak senkronize modda.

Bir parametre ileterek ve sonuç alarak kod biraz daha karmaşık görünecektir:

Class SampleThread, Thread'i genişletir ( korumalı işlev proses() ( return $this->getParam(0); ) ) $thread = new exampleThread(); $thread->bekle()->çalıştır(123); $sonuç = $thread->wait()->getResult();

Benzer şekilde, hafif bir el hareketiyle akıştan olay işlemeyi ekliyoruz:

Sınıf ÖrnekThread Thread'i genişletir ( const EV_PROCESS = "process"; protected function proses() ( $events = $this->getParam(0); for ($i = 0; $i tetikleyici(self::EV_PROCESS, $event_data); )) ) ) // Ek argüman. $ekArgüman = 123; $thread->bind(ExampleThread::EV_PROCESS, function($olay_adı, $olay_verisi, $ek_arg) ( // olay işleme), $additionalArgument); $olaylar = 10; // iş parçacığının oluşturacağı olayların sayısı // İlk çağrıdan önce iş parçacığını manuel olarak beklemekten kaçınmak için, // alt sınıftan $thread->wait(); preforkWait özelliğini TRUE olarak geçersiz kılabilirsiniz; $iş parçacığı = yeni ÖrnekThread(); $thread->run($olaylar)->bekle();

Ve son olarak, çalışma zamanı hata işleme ile sekiz iş parçacığından oluşan bir havuz kullanarak:

$threads = 8 // Thread sayısı $pool = new ThreadPool("ExampleThread", $threads); $sayı = 25; // Görev sayısı $sol = $sayı; // Kalan görev sayısı ( // Havuzda boş iş parçacıkları varsa // Ve hala yürütülecek görevlerimiz var while ($pool->hasWaiting() && $left > 0) ( // Başlarken şunu alırız: iş parçacığı kimliği $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( / / Görev başarıyla tamamlandı // Sonuç, // iş parçacığı kimliği ($threadId) $num--; ) ) if ($failed) ( // Yürütme hatalarını yönet. // İşin başarısız bir şekilde tamamlandığı kabul edilir // alt süreç yürütme sırasında öldüyse veya // görev yürütme için zaman aşımı dolduysa foreach ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Tüm alt süreçleri sonlandır. Havuzun kullandığı kaynakları temizliyoruz. $havuz->temizleme();

Performans Testi Sonuçları

Testleri Ubuntu 11.04 yüklü iki makinede yaptım.
Bunlardan ilki Intel Core i3 540 3.07 Ghz.
İkincisi Intel Core i7 2600K 3.40 Ghz'dir (Ubuntu, VMware sanal makinesinde çalışır).

Verimlilik artışını değerlendirebilmeniz için sonuçları basit bir şekilde sunuyorum. Yine, bunlar jps cinsinden testin 10 tekrarından oluşan bir serinin ortalama sonuçlarıdır (saniye başına iş - saniye başına görev sayısı).

Bir görev olarak iş parçacıkları aşağıdaki çöpleri gerçekleştirir:

İçin ($i = 0; $i

İlk sonuç senkron çalışma modu (çatalsız) için gösterilir. İlk konfigürasyonda 18 ve 20 iş parçacığını denemedim çünkü 12 iş parçacığında performans düşmeye başladı.

Konu sayısı İlk konfigürasyon Saniye
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

Yani işlemciye bağlı olarak performans 2-4 kat veya daha fazla artar!

Gerekli parametrelerle bir dizi testi çalıştıran kod, example/speed_test.php dosyasındadır. Böylece performansı kolayca test edebilir ve kendiniz için en uygun iş parçacığı sayısını seçebilirsiniz.

Kütüphanenin birine faydası olursa çok sevinirim. Herhangi bir özellik isteği veya tespit edilen hatalar Github'a bırakılabilir, kütüphaneyi derhal düzeltip geliştireceğim.

Görünüşe göre PHP geliştiricileri eşzamanlılığı nadiren kullanıyor. Senkronize kodun basitliğinden bahsetmeyeceğim; tek iş parçacıklı programlama elbette daha basit ve anlaşılırdır, ancak bazen paralelliğin biraz kullanılması performansta gözle görülür bir artış sağlayabilir.

Bu yazıda, pthreads uzantısını kullanarak PHP'de çoklu iş parçacığının nasıl sağlanabileceğine bir göz atacağız. Bunun için PHP 7.x'in ZTS (Zend Thread Safety) sürümünün ve pthreads v3 uzantısının kurulu olması gerekir. (PHP 7.1'in yazıldığı sırada, kullanıcıların pthreads deposundaki ana daldan yükleme yapmaları gerekecek - üçüncü taraf uzantısına bakın.)

Küçük bir açıklama: pthreads v2, PHP 5.x için tasarlanmıştır ve artık desteklenmemektedir, pthreads v3, PHP 7.x içindir ve aktif olarak geliştirilmektedir.

Bu kadar uzun bir aradan sonra hemen asıl meseleye geçelim!

Bir kerelik görevleri işleme

Bazen tek seferlik görevleri çok iş parçacıklı bir şekilde işlemek isteyebilirsiniz (örneğin, bazı G/Ç bağlantılı görevleri yürütmek). Bu gibi durumlarda, yeni bir iş parçacığı oluşturmak ve bazı işlemleri ayrı bir iş parçacığında çalıştırmak için Thread sınıfını kullanabilirsiniz.

Örneğin:

$görev = yeni sınıf Konuyu genişletiyor ( özel $yanıt; genel işlev run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $içerik, $eşleşmeler); $this->yanıt = $eşleşmeler; ) ); $görev->başlangıç() && $görev->join(); var_dump($görev->yanıt); // string (6) "Google"

Burada run yöntemi, yeni bir iş parçacığının içinde yürütülecek olan işlemimizdir. Thread::start çağrıldığında yeni bir iş parçacığı oluşturulur ve run yöntemi çağrılır. Daha sonra alt iş parçacığının yürütülmesi bitene kadar engellenecek olan Thread::join'i çağırarak alt iş parçacığını ana iş parçacığına geri bağlarız. Bu, sonucu yazdırmayı denemeden önce görevin yürütülmesinin tamamlanmasını sağlar (bu, $task->response'da saklanır).

Bir sınıfı akış mantığıyla ilişkili ek sorumluluklarla (bir çalıştırma yöntemi tanımlama sorumluluğu dahil) kirletmek istenmeyebilir. Bu tür sınıfları Threaded sınıfından miras alarak ayırt edebiliriz. Daha sonra başka bir iş parçacığının içinde çalıştırılabilirler:

Sınıf Görevi, İş Parçacığı'nı genişletir ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->yanıt = $eşleşir; ) ) $görev = yeni Görev; $iş parçacığı = yeni sınıf($görev) Konuyu genişletir ( özel $görev; public function __construct(Threaded $görev) ( $this->görev = $görev; ) public function run() ( $this->task->someWork( ); )); $thread->start() && $thread->join(); var_dump($görev->yanıt);

Ayrı bir iş parçacığında çalıştırılması gereken herhangi bir sınıf mutlak Threaded sınıfından miras alır. Bunun nedeni, farklı iş parçacıklarında işlem gerçekleştirmek için gerekli yeteneklerin yanı sıra örtülü güvenlik ve kullanışlı arayüzler (kaynak senkronizasyonu gibi) sağlamasıdır.

pthreads uzantısının sunduğu sınıf hiyerarşisine bir göz atalım:

İş Parçacığı (Geçilebilir, Toplanabilir uygular) İş Parçacığı Çalışanı Uçucu Havuzu

Thread ve Threaded sınıflarının temellerini zaten ele aldık ve öğrendik, şimdi diğer üçüne (Worker, Volatile ve Pool) bir göz atalım.

Konuları Yeniden Kullanma

Paralelleştirilmesi gereken her görev için yeni bir iş parçacığı başlatmak oldukça pahalıdır. Bunun nedeni, PHP'de çoklu iş parçacığının elde edilebilmesi için pthread'lerde ortak-hiçbir mimarinin uygulanması gerekmesidir. Bu, PHP yorumlayıcısının geçerli örneğinin tüm yürütme içeriğinin (her sınıf, arayüz, özellik ve işlev dahil) oluşturulan her iş parçacığı için kopyalanması gerektiği anlamına gelir. Bunun performansta gözle görülür bir etkisi olduğundan, akışın mümkün olduğunca her zaman yeniden kullanılması gerekir. İş parçacıkları iki şekilde yeniden kullanılabilir: İşçileri kullanarak veya Havuzları kullanarak.

Worker sınıfı, başka bir iş parçacığı içinde bir dizi görevi eşzamanlı olarak gerçekleştirmek için kullanılır. Bu, yeni bir Worker örneği oluşturarak (yeni bir iş parçacığı oluşturur) ve ardından görevleri bu ayrı iş parçacığının yığınına (Worker::stack kullanarak) aktararak yapılır.

İşte küçük bir örnek:

Sınıf Görevi, Dişli ( özel $değer; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Görev: ($this->value)'yi genişletir \n"; )) $işçi = yeni İşçi(); $işçi->başlat(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $işçi->kapatma();

Yukarıdaki örnekte, yeni bir $worker nesnesi için 15 görev Worker::stack yöntemi aracılığıyla yığına aktarılır ve daha sonra aktarıldıkları sıraya göre işlenirler. Yukarıda gösterildiği gibi Worker::collect yöntemi, görevlerin yürütülmesi biter bitmez temizlemek için kullanılır. Bununla birlikte, bir while döngüsü içinde, Worker::shutdown çağırmadan önce yığındaki tüm görevler tamamlanıp temizlenene kadar ana iş parçacığını bloke ederiz. Bir işçiyi erken sonlandırmak (yani hala tamamlanması gereken görevler varken), tüm görevlerin yürütülmesini tamamlayana kadar ana iş parçacığını yine de engelleyecektir, yalnızca görevler çöp olarak toplanmayacaktır (bu, temsil edilen bellek sızıntılarını gerektirir).

Worker sınıfı, görev yığınıyla ilgili diğer birkaç yöntemi sağlar; bunlar arasında son yığılmış görevi kaldırmak için Worker::unstack ve yürütme yığınındaki görev sayısını almak için Worker::getStacked bulunur. Bir işçi yığını yalnızca yürütülmesi gereken görevleri içerir. Yığındaki bir görev tamamlandığında kaldırılır ve çöp toplama için ayrı bir (dahili) yığına yerleştirilir (Worker::collect yöntemi kullanılarak).

Bir iş parçacığını birden çok görevde yeniden kullanmanın başka bir yolu da iş parçacığı havuzu kullanmaktır (Pool sınıfı aracılığıyla). Bir iş parçacığı havuzu, görevlerin yürütülmesini sağlamak için bir grup Çalışanı kullanır eşzamanlı havuz oluşturulduğunda eşzamanlılık faktörünün (birlikte çalıştığı havuz iş parçacığı sayısı) ayarlandığı .

Yukarıdaki örneği bir çalışan havuzunu kullanacak şekilde uyarlayalım:

Sınıf Görevi, Dişli ( özel $değer; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Görev: ($this->value)'yi genişletir \n"; )) $havuz = yeni Havuz(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $havuz->kapatma();

Havuz kullanımında işçi kullanımıyla karşılaştırıldığında birkaç dikkate değer fark vardır. Birincisi, havuzun manuel olarak başlatılmasına gerek yoktur; görevleri kullanılabilir hale gelir gelmez yürütmeye başlar. İkincisi, biz Göndermek havuza yönelik görevler değil onları bir yığına koy. Ek olarak, Pool sınıfı Threaded'dan miras almaz ve bu nedenle diğer thread'lere (Worker'ın aksine) aktarılamaz.

Nasıl İyi pratikÇalışanlar ve havuzlar için, her zaman görevlerini tamamlar tamamlamaz temizlemeli ve ardından manuel olarak sonlandırmalısınız. Thread sınıfı kullanılarak oluşturulan iş parçacıklarının da üst iş parçacığına eklenmesi gerekir.

pthread'ler ve (değişmez) değişkenlik

Değineceğimiz son sınıf, pthreads v3'e yeni eklenen Volatile'dir. Değişmezlik pthread'lerde önemli bir kavram haline geldi çünkü onsuz performans önemli ölçüde zarar görüyor. Bu nedenle, varsayılan olarak, kendileri de Threaded nesneler olan Threaded sınıflarının özellikleri artık değişmezdir ve bu nedenle, ilk atamalarından sonra bunların üzerine yazılamaz. Bu tür özellikler için açık değiştirilebilirlik şu anda tercih edilmektedir ve yeni Volatile sınıfı kullanılarak hala elde edilebilmektedir.

Yeni değişmezlik kısıtlamalarını gösterecek bir örneğe bakalım:

Sınıf Görevi, Dişli // Dişli bir sınıfı genişletir ( public function __construct() ( $this->data = new Threaded(); // $this->data, bir Dişli sınıfın Dişli özelliği olduğundan üzerine yazılamaz) ) $task = new class(new Task()) Thread'i genişletir ( // Threaded sınıfı, çünkü Thread, Threaded public function'ı genişletir __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // geçersiz, çünkü özellik bir Threaded sınıfının Threaded üyesidir ) );

Öte yandan Uçucu sınıfların iş parçacıklı özellikleri değiştirilebilir:

Sınıf Görevi Uçucuyu genişletir ( public function __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // geçerli, çünkü geçici bir sınıftayız ) ) $task = new class(new Task()) Thread'i genişletir ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // Volatile Threaded'i genişlettiğinden hala geçersiz, yani özellik hala Threaded sınıfının Threaded üyesidir $this->volatileMember = new StdClass(); ) );

Volatile sınıfının, Threaded özelliklerini değiştirme (aynı zamanda unset() işlevinin yanı sıra) yeteneğini sağlamak için ana Threaded sınıfı tarafından empoze edilen değişmezliği geçersiz kıldığını görebiliriz.

Değişkenlik ve Uçucu sınıf dizileri konusunu kapsayan başka bir tartışma konusu daha vardır. Pthread'lerde diziler, Threaded sınıfının bir özelliğine atandıklarında otomatik olarak Volatile nesnelerine dönüştürülür. Bunun nedeni, birden fazla PHP içeriğinden oluşan bir diziyi değiştirmenin güvenli olmamasıdır.

Bazı şeyleri daha iyi anlamak için tekrar bir örneğe bakalım:

$dizi = ; $görev = yeni sınıf($array) Thread'i genişletir ( özel $veri; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->veri = 4; $ this->veri = 5; print_r($this->veri); ) ); $görev->başlat() && $görev->join(); /* Çıktı: Uçucu Nesne ( => 1 => 2 => 3 => 4 => 5) */

Uçucu nesnelerin (yukarıda gösterildiği gibi) subset() operatörü gibi dizi işlemlerini destekledikleri için dizilermiş gibi ele alınabileceğini görüyoruz. Ancak Uçucu sınıflar array_pop ve array_shift gibi temel dizi işlevlerini desteklemez. Bunun yerine Threaded sınıfı bize yerleşik yöntemler gibi işlemler sağlar.

Bir gösteri olarak:

$data = yeni sınıf, Uçucuyu genişletiyor ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($veri); var_dump($data->pop()); var_dump($data->shift()); var_dump($veri); /* Çıktı: object(sınıf@anonim)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) object(sınıf@anonim)#1 (1) ( ["b"]=> int(2) ) */

Desteklenen diğer işlemler arasında Threaded::chunk ve Threaded::merge bulunur.

Senkronizasyon

Bu makalenin son bölümünde pthreads'te senkronizasyona bakacağız. Senkronizasyon, paylaşılan kaynaklara erişimi kontrol etmenize olanak tanıyan bir yöntemdir.

Örneğin basit bir sayaç uygulayalım:

$counter = yeni sınıf Konuyu genişletir ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $sayaç->başlat(); for ($i = 0; $i i; ) $counter->join(); var_dump($sayaç->i); // 10'dan 20'ye kadar bir sayı yazdıracağız

Senkronizasyon kullanılmadan çıktı deterministik değildir. Birden fazla iş parçacığı, kontrollü erişim olmadan aynı değişkene yazar; bu, güncellemelerin kaybolacağı anlamına gelir.

Zamanlama ekleyerek doğru çıktıyı 20 elde edecek şekilde bunu düzeltelim:

$counter = yeni sınıf Konuyu genişletir ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $sayaç->başlat(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($sayaç->i); // int(20)

Senkronize kod blokları ayrıca Threaded::wait ve Threaded::notify (veya Threaded::notifyAll) yöntemlerini kullanarak birbirleriyle iletişim kurabilir.

İşte iki senkronize while döngüsünde alternatif bir artış:

$counter = yeni sınıf Konuyu genişletir ( public $cond = 1; public function run() ( $this->synchronized(function () ( for ($i = 0; $i notify(); if ($this->cond) === 1) ( $this->koşul = 2; $this->bekle(); ) ) )); ) ); $sayaç->başlat(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // wait için ilk önce diğer başlayacak ) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ) , $sayaç); $counter->join(); /* Çıktı: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

fark edebilirsiniz ek koşullar, Threaded::wait çağrısının etrafına yerleştirildi. Bu koşullar kritiktir çünkü senkronize geri aramanın bir bildirim aldığında ve belirtilen koşul doğru olduğunda devam etmesine izin verirler. Bu önemlidir çünkü bildirimler Threaded::notify çağrıldığı zaman dışındaki yerlerden de gelebilir. Bu nedenle, eğer Threaded::wait yöntemine yapılan çağrılar koşulların içine alınmadıysa, çalıştıracağız. yanlış uyandırma çağrılarıöngörülemeyen kod davranışına yol açacaktır.

Çözüm

pthreads paketinin beş sınıfına (Threaded, Thread, Worker, Volatile ve Pool) ve her sınıfın nasıl kullanıldığına baktık. Ayrıca pthread'lerdeki yeni değişmezlik kavramına da baktık. kısa inceleme desteklenen senkronizasyon özellikleri. Bu temel bilgiler yerine getirildikten sonra artık pthread'lerin gerçek dünyadaki durumlarda nasıl kullanılabileceğine bakmaya başlayabiliriz! Bir sonraki yazımızın konusu bu olacak.

Bir sonraki gönderinin çevirisiyle ilgileniyorsanız bana bildirin: sosyal medyada yorum yapın. ağlar, olumlu oy verin ve gönderiyi meslektaşlarınız ve arkadaşlarınızla paylaşın.

Yükleniyor...Yükleniyor...