ພາສາອັງກິດພາສາຝຣັ່ງແອສປາໂຍນ

OnWorks favicon

perlthrtut - ອອນລາຍໃນຄລາວ

ແລ່ນ perlthrtut ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີຜ່ານ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator

ນີ້ແມ່ນຄໍາສັ່ງ perlthrtut ທີ່ສາມາດດໍາເນີນການໄດ້ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີໂດຍໃຊ້ຫນຶ່ງໃນຫຼາຍສະຖານີເຮັດວຽກອອນໄລນ໌ຂອງພວກເຮົາເຊັ່ນ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator

ໂຄງການ:

NAME


perlthrtut - ການສອນກ່ຽວກັບກະທູ້ໃນ Perl

ລາຍລະອຽດ


ບົດສອນນີ້ອະທິບາຍການໃຊ້ຫົວຂໍ້ແປພາສາ Perl (ບາງຄັ້ງເອີ້ນວ່າ
ຫົວຂໍ້). ໃນຮູບແບບນີ້, ແຕ່ລະກະທູ້ແລ່ນຢູ່ໃນຕົວແປ Perl ຂອງຕົນເອງ, ແລະຂໍ້ມູນໃດໆ
ການແບ່ງປັນລະຫວ່າງກະທູ້ຕ້ອງມີຄວາມຊັດເຈນ. ການໂຕ້ຕອບລະດັບຜູ້ໃຊ້ສໍາລັບ ຫົວຂໍ້ ໃຊ້ໄດ້
ປະເພດກະທູ້.

ຫມາຍ​ເຫດ​: ມີລົດຊາດກະທູ້ Perl ເກົ່າແກ່ອີກອັນໜຶ່ງທີ່ເອີ້ນວ່າແບບ 5.005 ທີ່ໃຊ້
ປະເພດກະທູ້. ຮູບແບບເກົ່ານີ້ເປັນທີ່ຮູ້ຈັກວ່າມີບັນຫາ, ຖືກຍົກເລີກ, ແລະຖືກໂຍກຍ້າຍ
ສໍາລັບການປ່ອຍ 5.10. ທ່ານໄດ້ຮັບການຊຸກຍູ້ຢ່າງແຂງແຮງໃຫ້ຍ້າຍລະຫັດຫົວຂໍ້ 5.005 ທີ່ມີຢູ່ແລ້ວ
ກັບຮູບແບບໃຫມ່ໃນທັນທີທີ່ເປັນໄປໄດ້.

ທ່ານ​ສາ​ມາດ​ເບິ່ງ​ທີ່ (ຫຼື​ບໍ່​ມີ​) ກິ່ນ​ຫອມ​ກະ​ທູ້​ທີ່​ທ່ານ​ມີ​ໂດຍ​ການ​ແລ່ນ "perl -V​" ແລະ​ຊອກ​ຫາ​
ຢູ່ໃນພາກ "ເວທີ". ຖ້າທ່ານມີ "useithreads = ກໍານົດ" ທ່ານມີ ithreads, ຖ້າທ່ານ
ມີ "use5005threads=define" ທ່ານມີ 5.005 threads. ຖ້າເຈົ້າບໍ່ມີ, ເຈົ້າບໍ່ມີ
ສະຫນັບສະຫນູນ thread ໃດ ກໍ່ ສ້າງ ໃນ.

ກະທູ້ແລະກະທູ້::ໂມດູນທີ່ແບ່ງປັນແມ່ນລວມຢູ່ໃນການແຈກຢາຍ Perl ຫຼັກ.
ນອກຈາກນັ້ນ, ພວກມັນຖືກຮັກສາໄວ້ເປັນໂມດູນແຍກຕ່າງຫາກໃນ CPAN, ດັ່ງນັ້ນທ່ານສາມາດກວດເບິ່ງໄດ້
ສຳ ລັບການປັບປຸງໃດໆ.

ແມ່ນ​ຫຍັງ Is A ກະທູ້ ເຖິງຢ່າງໃດກໍ່ຕາມ?


thread ແມ່ນການໄຫຼເຂົ້າຂອງການຄວບຄຸມໂດຍຜ່ານໂຄງການທີ່ມີຈຸດປະຕິບັດດຽວ.

ມັນເບິ່ງຄືວ່າເປັນຂະບວນການທີ່ ໜ້າ ຢ້ານ, ບໍ່ແມ່ນບໍ? ດີ, ມັນຄວນຈະ. ກະທູ້ແມ່ນຫນຶ່ງໃນ
ຕ່ອນຂອງຂະບວນການ. ທຸກໆຂະບວນການມີຢ່າງຫນ້ອຍຫນຶ່ງກະທູ້ແລະ, ຈົນກ່ວາໃນປັດຈຸບັນ, ທຸກໆ
ຂະບວນການແລ່ນ Perl ມີພຽງແຕ່ຫນຶ່ງກະທູ້. ດ້ວຍ 5.8, ເຖິງແມ່ນວ່າ, ທ່ານສາມາດສ້າງກະທູ້ພິເສດ.
ພວກເຮົາກໍາລັງຈະສະແດງໃຫ້ທ່ານຮູ້ວິທີ, ເວລາໃດ, ແລະຍ້ອນຫຍັງ.

ກະທູ້ ໂຄງການ ແບບຈໍາລອງ


ມີສາມວິທີພື້ນຖານທີ່ທ່ານສາມາດສ້າງໂຄງສ້າງໂຄງການ threaded. ທ່ານ​ແບບ​ໃດ
ເລືອກແມ່ນຂຶ້ນກັບສິ່ງທີ່ທ່ານຕ້ອງການໃຫ້ໂຄງການຂອງທ່ານເຮັດ. ສໍາລັບຈໍານວນຫຼາຍກະທູ້ທີ່ບໍ່ແມ່ນ trivial
ບັນດາໂຄງການ, ທ່ານ ຈຳ ເປັນຕ້ອງເລືອກຮູບແບບທີ່ແຕກຕ່າງກັນ ສຳ ລັບຊິ້ນສ່ວນຕ່າງໆຂອງໂຄງການຂອງທ່ານ.

ນາຍຈ້າງ/ພະນັກງານ
ຮູບແບບນາຍຈ້າງ / ພະນັກງານປົກກະຕິແລ້ວມີຫນຶ່ງ ນາຍຈ້າງ thread ແລະຫນຶ່ງຫຼືຫຼາຍກວ່ານັ້ນ ພະນັກງານ ກະທູ້. ໄດ້
ກະທູ້ນາຍຈ້າງລວບລວມຫຼືສ້າງວຽກງານທີ່ຕ້ອງເຮັດ, ຫຼັງຈາກນັ້ນ parcels ວຽກງານເຫຼົ່ານັ້ນອອກ
ກັບກະທູ້ແຮງງານທີ່ເຫມາະສົມ.

ຮູບແບບນີ້ແມ່ນທົ່ວໄປໃນ GUI ແລະໂປລແກລມເຊີບເວີ, ບ່ອນທີ່ຫົວຂໍ້ຕົ້ນຕໍລໍຖ້າເຫດການບາງຢ່າງ
ແລະຫຼັງຈາກນັ້ນຜ່ານເຫດການນັ້ນໄປຫາກະທູ້ພະນັກງານທີ່ເຫມາະສົມສໍາລັບການປຸງແຕ່ງ. ເມື່ອ
ເຫດການໄດ້ຜ່ານໄປ, ກະທູ້ນາຍຈ້າງກັບໄປລໍຖ້າເຫດການອື່ນ.

ກະທູ້ນາຍຈ້າງເຮັດວຽກຂ້ອນຂ້າງຫນ້ອຍ. ໃນຂະນະທີ່ວຽກງານບໍ່ຈໍາເປັນຕ້ອງປະຕິບັດ
ໄວກ່ວາວິທີການອື່ນໆ, ມັນມີແນວໂນ້ມທີ່ຈະມີເວລາຕອບສະຫນອງຜູ້ໃຊ້ທີ່ດີທີ່ສຸດ.

ການເຮັດວຽກ Crew
ໃນຮູບແບບລູກເຮືອເຮັດວຽກ, ຫຼາຍກະທູ້ຖືກສ້າງຂື້ນທີ່ເຮັດສິ່ງດຽວກັນກັບ
ຂໍ້ມູນທີ່ແຕກຕ່າງກັນ. ມັນສະທ້ອນເຖິງການປຸງແຕ່ງຂະຫນານຄລາສສິກແລະ vector ຢ່າງໃກ້ຊິດ
ໂປເຊດເຊີ, ບ່ອນທີ່ array ຂະຫນາດໃຫຍ່ຂອງໂປເຊດເຊີເຮັດສິ່ງດຽວກັນຄືກັນອ້ອຍຕ້ອຍກັບຫຼາຍຕ່ອນຂອງ
ຂໍ້ມູນ.

ຮູບແບບນີ້ແມ່ນເປັນປະໂຫຍດໂດຍສະເພາະຖ້າລະບົບທີ່ດໍາເນີນໂຄງການຈະແຈກຢາຍ
ຫຼາຍຫົວຂໍ້ໃນທົ່ວໂປເຊດເຊີທີ່ແຕກຕ່າງກັນ. ມັນຍັງສາມາດເປັນປະໂຫຍດໃນ ray tracing ຫຼື
rendering ເຄື່ອງຈັກ, ບ່ອນທີ່ກະທູ້ສ່ວນບຸກຄົນສາມາດສົ່ງຜົນໄດ້ຮັບຊົ່ວຄາວເພື່ອໃຫ້ໄດ້
ຄໍາ​ຄຶດ​ຄໍາ​ເຫັນ​ຂອງ​ຜູ້​ຊົມ​ໃຊ້​.

ທໍ່ນ້ໍາ
ຮູບ​ແບບ​ທໍ່​ນັ້ນ​ແບ່ງ​ໜ້າ​ວຽກ​ອອກ​ເປັນ​ຊຸດ​ຂອງ​ຂັ້ນ​ຕອນ, ແລະ​ຜ່ານ​ຜົນ​ອັນ​ໜຶ່ງ
ກ້າວໄປສູ່ການປະມວນຜົນກະທູ້ຕໍ່ໄປ. ແຕ່ລະກະທູ້ເຮັດສິ່ງດຽວກັບແຕ່ລະຊິ້ນ
ຂໍ້ມູນແລະສົ່ງຜົນໄດ້ຮັບໄປຫາຫົວຂໍ້ຕໍ່ໄປໃນແຖວ.

ຮູບແບບນີ້ເຮັດໃຫ້ຄວາມຮູ້ສຶກທີ່ສຸດຖ້າທ່ານມີໂປເຊດເຊີຫຼາຍຕົວດັ່ງນັ້ນສອງຫຼືຫຼາຍກວ່າກະທູ້
ຈະຖືກປະຕິບັດໃນຂະຫນານ, ເຖິງແມ່ນວ່າມັນມັກຈະມີຄວາມຫມາຍໃນສະພາບການອື່ນໆເຊັ່ນກັນ.
ມັນມີແນວໂນ້ມທີ່ຈະຮັກສາວຽກງານສ່ວນບຸກຄົນຂະຫນາດນ້ອຍແລະງ່າຍດາຍ, ເຊັ່ນດຽວກັນກັບການອະນຸຍາດໃຫ້ບາງສ່ວນຂອງ
ທໍ່ທີ່ຈະຕັນ (ໃນ I/O ຫຼືການໂທລະບົບ, ສໍາລັບການຍົກຕົວຢ່າງ) ໃນຂະນະທີ່ພາກສ່ວນອື່ນໆຍັງສືບຕໍ່.
ຖ້າທ່ານກໍາລັງແລ່ນພາກສ່ວນຕ່າງໆຂອງທໍ່ຢູ່ໃນໂປເຊດເຊີທີ່ແຕກຕ່າງກັນ, ເຈົ້າອາດຈະຄືກັນ
ໃຊ້ປະໂຫຍດຈາກຖານຄວາມຈໍາໃນແຕ່ລະໂປເຊດເຊີ.

ຮູບແບບນີ້ຍັງມີປະໂຫຍດສໍາລັບຮູບແບບການຂຽນໂປຼແກຼມ recursive ບ່ອນທີ່, ແທນທີ່ຈະມີ
subroutine ເອີ້ນຕົວມັນເອງ, ມັນແທນທີ່ຈະສ້າງຫົວຂໍ້ອື່ນ. Prime ແລະ Fibonacci generator
ທັງສອງແຜນທີ່ດີກັບຮູບແບບຂອງຮູບແບບທໍ່ນີ້. (ຮຸ່ນຂອງເຄື່ອງສ້າງຕົວເລກຫຼັກ
ຈະ​ນໍາ​ສະ​ເຫນີ​ຕໍ່​ມາ​.)

ແມ່ນ​ຫຍັງ ປະເພດ of ກະທູ້ ມີ Perl ກະທູ້?


ຖ້າທ່ານມີປະສົບການກັບການປະຕິບັດກະທູ້ອື່ນໆ, ທ່ານອາດຈະຊອກຫາສິ່ງນັ້ນ
ບໍ່ແມ່ນສິ່ງທີ່ເຈົ້າຄາດຫວັງ. ມັນເປັນສິ່ງສໍາຄັນຫຼາຍທີ່ຈະຈື່ຈໍາໃນເວລາທີ່ຈັດການກັບ Perl
ກະທູ້ວ່າ Perl Threads ມີ ບໍ່ X Threads ສໍາລັບຄ່າທັງໝົດຂອງ X. ມັນບໍ່ແມ່ນ POSIX
ກະທູ້, ຫຼື DecThreads, ຫຼືກະທູ້ສີຂຽວຂອງ Java, ຫຼືກະທູ້ Win32. ມີ
ຄວາມຄ້າຍຄືກັນ, ແລະແນວຄວາມຄິດທີ່ກວ້າງຂວາງແມ່ນຄືກັນ, ແຕ່ຖ້າທ່ານເລີ່ມຕົ້ນຊອກຫາ
ລາຍລະອຽດການປະຕິບັດທີ່ທ່ານກໍາລັງຈະຜິດຫວັງຫຼືສັບສົນ. ອາດຈະເປັນທັງສອງ.

ນີ້ບໍ່ແມ່ນການເວົ້າວ່າກະທູ້ Perl ແມ່ນແຕກຕ່າງກັນຫມົດຈາກທຸກສິ່ງທີ່ເຄີຍ
ມາກ່ອນ. ເຂົາເຈົ້າບໍ່ແມ່ນ. ຮູບແບບກະທູ້ຂອງ Perl ເປັນໜີ້ຫຼາຍກັບຕົວແບບກະທູ້ອື່ນໆ,
ໂດຍສະເພາະ POSIX. ເຊັ່ນດຽວກັນກັບ Perl ບໍ່ແມ່ນ C, ເຖິງແມ່ນວ່າ, Perl threads ບໍ່ແມ່ນ POSIX threads. ດັ່ງນັ້ນ
ຖ້າທ່ານຊອກຫາຕົວທ່ານເອງຊອກຫາ mutexes, ຫຼືຫົວຂໍ້ບູລິມະສິດ, ມັນແມ່ນເວລາທີ່ຈະກ້າວກັບຄືນ a
bit ແລະຄິດກ່ຽວກັບສິ່ງທີ່ທ່ານຕ້ອງການທີ່ຈະເຮັດແລະວິທີການ Perl ສາມາດເຮັດໄດ້.

ຢ່າງໃດກໍ່ຕາມ, ມັນເປັນສິ່ງສໍາຄັນທີ່ຈະຈື່ຈໍາວ່າກະທູ້ Perl ບໍ່ສາມາດເຮັດສິ່ງມະຫັດສະຈັນໄດ້ເວັ້ນເສຍແຕ່
ກະທູ້ຂອງລະບົບປະຕິບັດການຂອງທ່ານອະນຸຍາດໃຫ້ມັນ. ດັ່ງນັ້ນຖ້າຫາກວ່າລະບົບຂອງທ່ານຕັນຂະບວນການທັງຫມົດກ່ຽວກັບ
"sleep()", Perl ປົກກະຕິແລ້ວຈະ, ເຊັ່ນດຽວກັນ.

Perl Threads ມີ ແຕກຕ່າງ.

ກະທູ້ປອດໄພ ໂມດູນ


ການເພີ່ມກະທູ້ໄດ້ປ່ຽນແປງພາຍໃນຂອງ Perl ຢ່າງຫຼວງຫຼາຍ. ມີຜົນສະທ້ອນ
ສໍາລັບຜູ້ທີ່ຂຽນໂມດູນທີ່ມີລະຫັດ XS ຫຼືຫ້ອງສະຫມຸດພາຍນອກ. ຢ່າງໃດກໍຕາມ, ນັບຕັ້ງແຕ່ຂໍ້ມູນ Perl
ບໍ່ໄດ້ຖືກແບ່ງປັນລະຫວ່າງກະທູ້ຕາມຄ່າເລີ່ມຕົ້ນ, ໂມດູນ Perl ມີໂອກາດສູງທີ່ຈະເປັນ thread-
ປອດໄພຫຼືສາມາດເຮັດ thread-ປອດໄພໄດ້ຢ່າງງ່າຍດາຍ. ໂມດູນທີ່ບໍ່ໄດ້ຖືກ tagged ເປັນ thread-safe ຄວນ
ໄດ້ຮັບການທົດສອບຫຼືລະຫັດການທົບທວນຄືນກ່ອນທີ່ຈະຖືກນໍາໃຊ້ໃນລະຫັດການຜະລິດ.

ບໍ່ແມ່ນທຸກໂມດູນທີ່ເຈົ້າອາດຈະໃຊ້ແມ່ນປອດໄພຕໍ່ກະທູ້, ແລະເຈົ້າຄວນຄິດເປັນໂມດູນສະເໝີ
ແມ່ນບໍ່ປອດໄພເວັ້ນເສຍແຕ່ເອກະສານລະບຸວ່າຖ້າບໍ່ດັ່ງນັ້ນ. ນີ້ປະກອບມີໂມດູນທີ່ມີ
ແຈກຢາຍເປັນສ່ວນຫນຶ່ງຂອງຫຼັກ. ກະທູ້ເປັນລັກສະນະທີ່ຂ້ອນຂ້າງໃຫມ່, ແລະແມ້ກະທັ້ງບາງ
ໂມດູນມາດຕະຖານບໍ່ປອດໄພກະທູ້.

ເຖິງແມ່ນວ່າໂມດູນມີຄວາມປອດໄພກະທູ້, ມັນບໍ່ໄດ້ຫມາຍຄວາມວ່າໂມດູນຖືກປັບປຸງໃຫ້ເຮັດວຽກໄດ້ດີ
ກັບກະທູ້. ໂມດູນອາດຈະຖືກຂຽນຄືນໃຫມ່ເພື່ອນໍາໃຊ້ຄຸນສົມບັດໃຫມ່ໃນ threaded
Perl ເພື່ອເພີ່ມປະສິດທິພາບໃນສະພາບແວດລ້ອມ threaded.

ຖ້າເຈົ້າໃຊ້ໂມດູນທີ່ບໍ່ປອດໄພດ້ວຍເຫດຜົນບາງຢ່າງ, ເຈົ້າສາມາດປ້ອງກັນຕົວເອງໄດ້
ໂດຍການນໍາໃຊ້ມັນຈາກຫນຶ່ງ, ແລະພຽງແຕ່ຫນຶ່ງ thread ທັງຫມົດ. ຖ້າທ່ານຕ້ອງການຫຼາຍຫົວຂໍ້ເພື່ອເຂົ້າເຖິງ
ໂມດູນດັ່ງກ່າວ, ທ່ານສາມາດນໍາໃຊ້ semaphores ແລະລະບຽບວິໄນການຂຽນໂປລແກລມຈໍານວນຫລາຍເພື່ອຄວບຄຸມການເຂົ້າເຖິງ
ກັບມັນ. Semaphores ແມ່ນກວມເອົາໃນ "semaphores ພື້ນຖານ".

ເບິ່ງ "Thread-Safety of System Libraries".

ກະທູ້ ຄວາມຮູ້ພື້ນຖານ


ໂມດູນ threads ສະຫນອງຫນ້າທີ່ພື້ນຖານທີ່ທ່ານຈໍາເປັນຕ້ອງຂຽນໂປຼແກຼມ threaded. ໃນ
ພາກສ່ວນຕໍ່ໄປນີ້, ພວກເຮົາຈະກວມເອົາພື້ນຖານ, ສະແດງໃຫ້ທ່ານເຫັນສິ່ງທີ່ທ່ານຕ້ອງເຮັດເພື່ອສ້າງ
ໂຄງ​ການ​ກະ​ທູ້​. ຫຼັງຈາກນັ້ນ, ພວກເຮົາຈະຜ່ານບາງລັກສະນະຂອງໂມດູນກະທູ້
ທີ່ເຮັດໃຫ້ການຂຽນໂປຼແກຼມ threaded ງ່າຍຂຶ້ນ.

ພື້ນຖານ ກະທູ້ ສະຫນັບສະຫນູນ
ການສະຫນັບສະຫນູນກະທູ້ແມ່ນທາງເລືອກ Perl ເວລາລວບລວມ. ມັນແມ່ນບາງສິ່ງບາງຢ່າງທີ່ເປີດຫຼືປິດໃນເວລາທີ່
Perl ຖືກສ້າງຂຶ້ນຢູ່ໃນເວັບໄຊຂອງທ່ານ, ແທນທີ່ຈະກ່ວາເວລາທີ່ໂຄງການຂອງທ່ານຖືກລວບລວມ. ຖ້າ Perl ຂອງທ່ານ
ບໍ່ໄດ້ຖືກລວບລວມດ້ວຍການຮອງຮັບກະທູ້, ຈາກນັ້ນຄວາມພະຍາຍາມໃດໆທີ່ຈະໃຊ້ກະທູ້ຈະລົ້ມເຫລວ.

ໂປລແກລມຂອງເຈົ້າສາມາດໃຊ້ໂມດູນ Config ເພື່ອກວດເບິ່ງວ່າກະທູ້ຖືກເປີດໃຊ້ງານຫຼືບໍ່. ຖ້າເຈົ້າ
ໂຄງການບໍ່ສາມາດດໍາເນີນການໄດ້ໂດຍບໍ່ມີພວກມັນ, ທ່ານສາມາດເວົ້າບາງສິ່ງບາງຢ່າງເຊັ່ນ:

ໃຊ້ Config;
$Config{useithreads} ຫຼື
die('Recompile Perl with threads to run this program.');

ໂປລແກລມທີ່ອາດຈະເປັນກະທູ້ໂດຍໃຊ້ໂມດູນທີ່ມີກະທູ້ທີ່ເປັນໄປໄດ້ອາດຈະມີລະຫັດແບບນີ້:

ໃຊ້ Config;
ໃຊ້ MyMod;

{
ຖ້າ ($Config{useithreads}) {
#ພວກເຮົາມີກະທູ້
ຕ້ອງການ MyMod_threaded;
ນໍາເຂົ້າ MyMod_threaded;
} else {
ຕ້ອງການ MyMod_unthreaded;
ນໍາເຂົ້າ MyMod_unthreaded;
}
}

ເນື່ອງຈາກວ່າລະຫັດທີ່ແລ່ນທັງມີແລະບໍ່ມີກະທູ້ແມ່ນປົກກະຕິແລ້ວ messy pretty, ມັນດີທີ່ສຸດທີ່ຈະ
ແຍກລະຫັດສະເພາະກະທູ້ຢູ່ໃນໂມດູນຂອງມັນເອງ. ໃນຕົວຢ່າງຂອງພວກເຮົາຂ້າງເທິງ, ນັ້ນແມ່ນສິ່ງທີ່
"MyMod_threaded" ແມ່ນ, ແລະມັນຖືກນໍາເຂົ້າພຽງແຕ່ຖ້າພວກເຮົາເຮັດວຽກຢູ່ໃນ Perl threaded.

A ຫມາຍ​ເຫດ​ ກ່ຽວກັບ ໄດ້ ຕົວຢ່າງ
ໃນສະຖານະການທີ່ແທ້ຈິງ, ຄວນລະມັດລະວັງວ່າກະທູ້ທັງຫມົດແມ່ນສໍາເລັດການປະຕິບັດກ່ອນ
ໂຄງ​ການ​ອອກ​. ການດູແລນັ້ນມີ ບໍ່ ໄດ້ຖືກປະຕິບັດຢູ່ໃນຕົວຢ່າງເຫຼົ່ານີ້ໃນຄວາມສົນໃຈຂອງ
ຄວາມລຽບງ່າຍ. ແລ່ນຕົວຢ່າງເຫຼົ່ານີ້ as is ຈະຜະລິດຂໍ້ຄວາມຄວາມຜິດພາດ, ປົກກະຕິແລ້ວເກີດມາຈາກ
ຄວາມຈິງທີ່ວ່າຍັງມີກະທູ້ທີ່ເຮັດວຽກໃນເວລາທີ່ໂຄງການອອກ. ເຈົ້າບໍ່ຄວນເປັນ
ເປັນຕາຕົກໃຈໂດຍນີ້.

ການສ້າງ Threads
ໂມດູນກະທູ້ໃຫ້ເຄື່ອງມືທີ່ທ່ານຕ້ອງການເພື່ອສ້າງຫົວຂໍ້ໃຫມ່. ເຊັ່ນດຽວກັບອື່ນໆ
ໂມດູນ, ທ່ານຈໍາເປັນຕ້ອງບອກ Perl ວ່າທ່ານຕ້ອງການໃຊ້ມັນ; "ໃຊ້ກະທູ້;" ການ​ນໍາ​ເຂົ້າ​ທັງ​ຫມົດ​
ຕ່ອນທີ່ທ່ານຕ້ອງການເພື່ອສ້າງກະທູ້ພື້ນຖານ.

ວິທີທີ່ງ່າຍທີ່ສຸດ, ກົງໄປກົງມາທີ່ສຸດໃນການສ້າງກະທູ້ແມ່ນ "ສ້າງ():

ໃຊ້ກະທູ້;

$thr = threads->create(\&sub1);

ຍ່ອຍຍ່ອຍ 1 {
print("ໃນກະທູ້\n");
}

ວິທີການ "create()" ໃຊ້ການອ້າງອີງເຖິງການຍ່ອຍ ແລະສ້າງຫົວຂໍ້ໃໝ່
ເລີ່ມຕົ້ນປະຕິບັດໃນການເຮັດວຽກຍ່ອຍທີ່ອ້າງອີງ. ຫຼັງຈາກນັ້ນ, ການຄວບຄຸມທັງສອງຈະສົ່ງຕໍ່ subroutine
ແລະຜູ້ໂທ.

ຖ້າທ່ານຕ້ອງການ, ໂປລແກລມຂອງທ່ານສາມາດສົ່ງພາລາມິເຕີໄປຫາ routine ຍ່ອຍເປັນສ່ວນຫນຶ່ງຂອງກະທູ້
ເລີ່ມ​ຕົ້ນ. ພຽງແຕ່ລວມເອົາບັນຊີລາຍຊື່ຂອງຕົວກໍານົດການເປັນສ່ວນຫນຶ່ງຂອງ "threads->create()" call,
ເຊັ່ນນີ້:

ໃຊ້ກະທູ້;

$Param3 = 'foo' ຂອງຂ້ອຍ;
$thr1 = threads->create(\&sub1, 'Param 1', 'Param 2', $Param3);
my @ParamList = (42, 'ສະບາຍດີ', 3.14);
$thr2 = threads->create(\&sub1, @ParamList);
$thr3 = threads->create(\&sub1, qw(Param1 Param2 Param3));

ຍ່ອຍຍ່ອຍ 1 {
@InboundParameters ຂອງຂ້ອຍ = @_;
print("ໃນກະທູ້\n");
print('Got parameters >', join('<>',@InboundParameters), "<\n");
}

ຕົວຢ່າງສຸດທ້າຍສະແດງໃຫ້ເຫັນລັກສະນະອື່ນຂອງກະທູ້. ທ່ານສາມາດ spawn ອອກຫຼາຍ
ກະທູ້ທີ່ໃຊ້ວຽກຍ່ອຍດຽວກັນ. ແຕ່ລະກະທູ້ປະຕິບັດໜ້າທີ່ຍ່ອຍດຽວກັນ, ແຕ່ໃນ a
ກະທູ້ແຍກຕ່າງຫາກທີ່ມີສະພາບແວດລ້ອມແຍກຕ່າງຫາກແລະການໂຕ້ຖຽງທີ່ອາດຈະແຍກຕ່າງຫາກ.

"new()" ແມ່ນຄໍາສັບຄ້າຍຄື "create()".

ລໍຖ້າ ສໍາລັບການ A ກະທູ້ To ການທ່ອງທ່ຽວ
ເນື່ອງຈາກກະທູ້ແມ່ນຍັງເປັນ subroutines, ພວກເຂົາສາມາດສົ່ງຄືນຄ່າ. ເພື່ອລໍຖ້າກະທູ້ອອກ
ແລະສະກັດຄ່າໃດໆທີ່ມັນອາດຈະກັບຄືນມາ, ທ່ານສາມາດນໍາໃຊ້ວິທີການ "ເຂົ້າຮ່ວມ()":

ໃຊ້ກະທູ້;

my ($thr) = threads->create(\&sub1);

@ReturnData ຂອງຂ້ອຍ = $thr->ເຂົ້າຮ່ວມ();
print('Thread return ', join(', ', @ReturnData), "\n");

sub sub1 { return ('ຫ້າສິບຫົກ', 'foo', 2); }

ໃນຕົວຢ່າງຂ້າງເທິງ, ວິທີການ "join()" ຈະກັບຄືນມາທັນທີທີ່ກະທູ້ສິ້ນສຸດລົງ. ເພີ່ມ​ເຕີມ
ເພື່ອລໍຖ້າກະທູ້ສໍາເລັດຮູບແລະລວບລວມຄຸນຄ່າໃດໆທີ່ກະທູ້ອາດຈະມີ
ກັບຄືນມາ, "ເຂົ້າຮ່ວມ()" ຍັງປະຕິບັດການທໍາຄວາມສະອາດ OS ທີ່ຈໍາເປັນສໍາລັບກະທູ້. ການອະນາໄມນັ້ນ
ອາດຈະມີຄວາມສໍາຄັນ, ໂດຍສະເພາະສໍາລັບໂຄງການທີ່ຍາວໄກທີ່ spawn ຫຼາຍກະທູ້. ຖ້າ
ທ່ານບໍ່ຕ້ອງການຄ່າກັບຄືນແລະບໍ່ຕ້ອງການລໍຖ້າໃຫ້ກະທູ້ສໍາເລັດ, ເຈົ້າ
ຄວນເອີ້ນວິທີ "detach()" ແທນ, ດັ່ງທີ່ອະທິບາຍຕໍ່ໄປ.

ຫມາຍເຫດ: ໃນຕົວຢ່າງຂ້າງເທິງ, ກະທູ້ສົ່ງຄືນບັນຊີລາຍຊື່, ດັ່ງນັ້ນຈຶ່ງຈໍາເປັນວ່າ thread
ການສ້າງການໂທຈະຖືກເຮັດໃນບໍລິບົດລາຍການ (ie, "my ($thr)"). ເບິ່ງ "$thr->ເຂົ້າຮ່ວມ ()"ໃນກະທູ້
ແລະ "THREAD CONTEXT" ໃນຫົວຂໍ້ສໍາລັບລາຍລະອຽດເພີ່ມເຕີມກ່ຽວກັບບໍລິບົດຫົວຂໍ້ແລະຄ່າກັບຄືນ.

ບໍ່ສົນໃຈ A ກະທູ້
"ເຂົ້າຮ່ວມ ()" ເຮັດສາມຢ່າງ: ມັນລໍຖ້າເສັ້ນທີ່ຈະອອກ, ເຮັດຄວາມສະອາດຫຼັງຈາກມັນ, ແລະກັບຄືນມາ.
ຂໍ້ມູນໃດໆທີ່ກະທູ້ອາດຈະຜະລິດ. ແຕ່ສິ່ງທີ່ຖ້າຫາກວ່າທ່ານບໍ່ສົນໃຈໃນກະທູ້ຂອງ
ກັບຄືນຄ່າ, ແລະເຈົ້າບໍ່ສົນໃຈແທ້ໆເມື່ອກະທູ້ສໍາເລັດ? ທັງ​ຫມົດ​ທີ່​ທ່ານ​ຕ້ອງ​ການ​ແມ່ນ​ສໍາ​ລັບ​ການ​
ກະທູ້ເພື່ອເຮັດຄວາມສະອາດຫຼັງຈາກມັນສໍາເລັດ.

ໃນກໍລະນີນີ້, ທ່ານໃຊ້ວິທີການ "detach()". ເມື່ອກະທູ້ຖືກແຍກອອກ, ມັນຈະດໍາເນີນການຈົນກ່ວາ
ມັນຈົບແລ້ວ; ຫຼັງຈາກນັ້ນ Perl ຈະເຮັດຄວາມສະອາດຫຼັງຈາກມັນອັດຕະໂນມັດ.

ໃຊ້ກະທູ້;

$thr = threads->create(\&sub1); # ວາງສາຍ

$thr->detach(); # ດຽວນີ້ພວກເຮົາບໍ່ສົນໃຈອີກຕໍ່ໄປ

ນອນ(15); # ຂໍໃຫ້ກະທູ້ແລ່ນໄປຊົ່ວໄລຍະໜຶ່ງ

ຍ່ອຍຍ່ອຍ 1 {
$count ຂອງຂ້ອຍ = 0;
ໃນຂະນະທີ່ (1) {
$count++;
print("\$count ແມ່ນ $count\n");
ນອນ(1)
}
}

ເມື່ອກະທູ້ຖືກແຍກອອກ, ມັນອາດຈະບໍ່ຖືກເຂົ້າຮ່ວມ, ແລະຂໍ້ມູນໃດໆທີ່ມັນອາດມີ
ຜະລິດ (ຖ້າມັນຖືກເຮັດແລະລໍຖ້າການເຂົ້າຮ່ວມ) ແມ່ນສູນເສຍ.

"detach()" ຍັງສາມາດເອີ້ນວ່າເປັນວິທີການຫ້ອງຮຽນເພື່ອໃຫ້ thread ແຍກຕົວຂອງມັນເອງ:

ໃຊ້ກະທູ້;

$thr = threads->create(\&sub1);

ຍ່ອຍຍ່ອຍ 1 {
threads->detach();
#ເຮັດວຽກຫຼາຍ
}

ຂະບວນການ ແລະ ກະທູ້ ການສິ້ນສຸດ
ດ້ວຍຫົວຂໍ້ຫນຶ່ງຕ້ອງລະມັດລະວັງເພື່ອເຮັດໃຫ້ແນ່ໃຈວ່າພວກເຂົາທັງຫມົດມີໂອກາດທີ່ຈະດໍາເນີນການສໍາເລັດ,
ສົມມຸດວ່ານັ້ນແມ່ນສິ່ງທີ່ທ່ານຕ້ອງການ.

ການປະຕິບັດທີ່ຢຸດຂະບວນການຈະສິ້ນສຸດ ທັງຫມົດ ກະທູ້ແລ່ນ. ຕາຍ ແລະ ອອກຈາກ ()
ມີຄຸນສົມບັດນີ້, ແລະ perl ເຮັດທາງອອກໃນເວລາທີ່ກະທູ້ຕົ້ນຕໍອອກ, ບາງທີອາດມີ implicitly
ໂດຍການຕົກອອກຈາກທ້າຍລະຫັດຂອງທ່ານ, ເຖິງແມ່ນວ່າມັນບໍ່ແມ່ນສິ່ງທີ່ທ່ານຕ້ອງການ.

ໃນ​ຖາ​ນະ​ເປັນ​ຕົວ​ຢ່າງ​ຂອງ​ກໍ​ລະ​ນີ​ນີ້​, ລະ​ຫັດ​ນີ້​ພິມ​ຂໍ້​ຄວາມ "Perl exited with active threads:
2 ແລ່ນແລະບໍ່ໄດ້ເຂົ້າຮ່ວມ":

ໃຊ້ກະທູ້;
ຂອງຂ້ອຍ $thr1 = threads->new(\&thrsub, "test1");
ຂອງຂ້ອຍ $thr2 = threads->new(\&thrsub, "test2");
sub thrsub {
my ($message) = @_;
ນອນ 1;
ພິມ "ກະທູ້ $message\n";
}

ແຕ່ເມື່ອເສັ້ນຕໍ່ໄປນີ້ຖືກເພີ່ມໃນຕອນທ້າຍ:

$thr1->ເຂົ້າຮ່ວມ();
$thr2->ເຂົ້າຮ່ວມ();

ມັນພິມອອກສອງເສັ້ນ, ບາງທີຜົນໄດ້ຮັບທີ່ເປັນປະໂຫຍດກວ່າ.

Threads ແລະ ຂໍ້ມູນ


ໃນປັດຈຸບັນທີ່ພວກເຮົາໄດ້ກວມເອົາພື້ນຖານຂອງກະທູ້, ມັນແມ່ນເວລາສໍາລັບຫົວຂໍ້ຕໍ່ໄປຂອງພວກເຮົາ: ຂໍ້ມູນ.
Threading ແນະນໍາສອງອາການແຊກຊ້ອນໃນການເຂົ້າເຖິງຂໍ້ມູນວ່າໂຄງການທີ່ບໍ່ແມ່ນກະທູ້
ບໍ່ຈໍາເປັນຕ້ອງກັງວົນກ່ຽວກັບ.

ແບ່ງປັນ ແລະ ບໍ່ໄດ້ແບ່ງປັນ ຂໍ້ມູນ
ຄວາມແຕກຕ່າງທີ່ໃຫຍ່ທີ່ສຸດລະຫວ່າງ Perl ຫົວຂໍ້ ແລະແບບເກົ່າ 5.005 threading, ຫຼືສໍາລັບ
ສິ່ງນັ້ນ, ສໍາລັບລະບົບ threading ອື່ນໆສ່ວນໃຫຍ່ຢູ່ທີ່ນັ້ນ, ແມ່ນວ່າໂດຍຄ່າເລີ່ມຕົ້ນ, ບໍ່ມີຂໍ້ມູນໃດໆ
ແບ່ງປັນ. ເມື່ອກະທູ້ Perl ໃຫມ່ຖືກສ້າງຂື້ນ, ຂໍ້ມູນທັງຫມົດທີ່ກ່ຽວຂ້ອງກັບກະທູ້ປະຈຸບັນ
ຖືກຄັດລອກໃສ່ກະທູ້ໃໝ່, ແລະຕໍ່ມາກໍເປັນສ່ວນຕົວກັບຫົວຂໍ້ໃໝ່ນັ້ນ! ນີ້​ແມ່ນ
ຄ້າຍຄືກັນກັບຄວາມຮູ້ສຶກທີ່ເກີດຂື້ນໃນເວລາທີ່ຂະບວນການ Unix ສ້ອມແຊມ, ຍົກເວັ້ນວ່າໃນກໍລະນີນີ້, ໄດ້
ຂໍ້ມູນພຽງແຕ່ຖືກຄັດລອກໄປຫາສ່ວນທີ່ແຕກຕ່າງກັນຂອງຫນ່ວຍຄວາມຈໍາພາຍໃນຂະບວນການດຽວກັນແທນທີ່ຈະເປັນ
ສ້ອມທີ່ແທ້ຈິງເກີດຂຶ້ນ.

ເພື່ອເຮັດໃຫ້ການນໍາໃຊ້ຂອງ threading, ຢ່າງໃດກໍຕາມ, ຫນຶ່ງປົກກະຕິແລ້ວຕ້ອງການກະທູ້ທີ່ຈະແບ່ງປັນຢ່າງຫນ້ອຍບາງ
ຂໍ້​ມູນ​ລະ​ຫວ່າງ​ຕົນ​ເອງ​. ນີ້ແມ່ນເຮັດກັບຫົວຂໍ້::shared module ແລະ ":shared"
attribute:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::shared;

$foo ຂອງຂ້ອຍ :shared = 1;
$bar ຂອງຂ້ອຍ = 1;
threads->create(sub { $foo++; $bar++; })->join();

ພິມ("$foo\n"); # ພິມ 2 ຕັ້ງແຕ່ $foo ຖືກແບ່ງປັນ
ພິມ("$bar\n"); # ພິມ 1 ເນື່ອງຈາກ $bar ບໍ່ໄດ້ແບ່ງປັນ

ໃນກໍລະນີຂອງ array ທີ່ໃຊ້ຮ່ວມກັນ, ອົງປະກອບທັງຫມົດຂອງ array ຈະຖືກແບ່ງປັນ, ແລະສໍາລັບ hash ທີ່ໃຊ້ຮ່ວມກັນ,
ກະແຈ ແລະຄ່າທັງໝົດຖືກແບ່ງປັນ. ນີ້ວາງຂໍ້ຈໍາກັດກ່ຽວກັບສິ່ງທີ່ອາດຈະຖືກມອບຫມາຍໃຫ້
array ແລະອົງປະກອບ hash ທີ່ໃຊ້ຮ່ວມກັນ: ພຽງແຕ່ຄ່າງ່າຍດາຍຫຼືການອ້າງອີງເຖິງຕົວແປທີ່ແບ່ງປັນເທົ່ານັ້ນ
ອະນຸຍາດ - ນີ້ແມ່ນເພື່ອໃຫ້ຕົວແປສ່ວນຕົວບໍ່ສາມາດຖືກແບ່ງປັນໂດຍບັງເອີນ. ບໍ່ດີ
ການມອບໝາຍຈະເຮັດໃຫ້ກະທູ້ຕາຍ. ຍົກ​ຕົວ​ຢ່າງ:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::shared;

$var ຂອງຂ້ອຍ = 1;
$svar ຂອງຂ້ອຍ :shared = 2;
%hash ຂອງຂ້ອຍ :shared;

... ສ້າງບາງກະທູ້ ...

$hash{a} = 1; # ກະທູ້ທັງໝົດເຫັນວ່າມີຢູ່ ($hash{a})
# ແລະ $hash{a} == 1
$hash{a} = $var; # okay - copy-by-value: ຜົນກະທົບດຽວກັນກັບທີ່ຜ່ານມາ
$hash{a} = $svar; # okay - copy-by-value: ຜົນກະທົບດຽວກັນກັບທີ່ຜ່ານມາ
$hash{a} = \$svar; # ຕົກລົງ - ການອ້າງອີງເຖິງຕົວແປທີ່ແບ່ງປັນ
$hash{a} = \$var; # ອັນນີ້ຈະຕາຍ
ລຶບ($hash{a}); # ຕົກລົງ - ກະທູ້ທັງໝົດຈະເຫັນ !exists($hash{a})

ໃຫ້ສັງເກດວ່າຕົວແປທີ່ແບ່ງປັນຮັບປະກັນວ່າຖ້າສອງຫຼືຫຼາຍກວ່າກະທູ້ພະຍາຍາມດັດແປງມັນຢູ່ທີ່
ໃນເວລາດຽວກັນ, ສະຖານະພາຍໃນຂອງຕົວແປຈະບໍ່ເສຍຫາຍ. ຢ່າງໃດກໍຕາມ, ຢູ່ທີ່ນັ້ນ
ບໍ່ມີການຮັບປະກັນເກີນກວ່ານີ້, ດັ່ງທີ່ໄດ້ອະທິບາຍໄວ້ໃນພາກຕໍ່ໄປ.

ກະທູ້ ຂຸມ: ສາຍພັນ
ໃນຂະນະທີ່ກະທູ້ນໍາເອົາຊຸດໃຫມ່ຂອງເຄື່ອງມືທີ່ເປັນປະໂຫຍດ, ພວກເຂົາເຈົ້າຍັງນໍາເອົາຈໍານວນ pitfalls. ຫນຶ່ງ
ຂຸມ​ແມ່ນ​ສະ​ພາບ​ການ​ເຊື້ອ​ຊາດ​:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::shared;

$x ຂອງຂ້ອຍ :shared = 1;
$thr1 = threads->create(\&sub1);
$thr2 = threads->create(\&sub2);

$thr1->ເຂົ້າຮ່ວມ();
$thr2->ເຂົ້າຮ່ວມ();
ພິມ("$x\n");

sub1 { ຂອງຂ້ອຍ $foo = $x; $x = $foo + 1; }
sub2 { ຂອງຂ້ອຍ $bar = $x; $x = $bar + 1; }

ເຈົ້າຄິດວ່າ $x ຈະເປັນແນວໃດ? ຄໍາຕອບ, ແຕ່ຫນ້າເສຍດາຍ, ແມ່ນ it ຂຶ້ນຢູ່ກັບ. ທັງ "sub1()" ແລະ
"sub2()" ເຂົ້າເຖິງຕົວແປທົ່ວໂລກ $x, ເມື່ອອ່ານແລະຂຽນຄັ້ງດຽວ. ຂຶ້ນກັບ
ປັດ​ໄຈ​ນັບ​ຕັ້ງ​ແຕ່ algorithm ການ​ກໍາ​ນົດ​ເວ​ລາ​ການ​ປະ​ຕິ​ບັດ​ກະ​ທູ້​ຂອງ​ທ່ານ​ກັບ​ໄລ​ຍະ​ຂອງ​ການ​
ເດືອນ, $x ສາມາດເປັນ 2 ຫຼື 3.

ເງື່ອນໄຂຂອງເຊື້ອຊາດແມ່ນເກີດມາຈາກການເຂົ້າເຖິງຂໍ້ມູນທີ່ແບ່ງປັນໂດຍ unsynchronized. ໂດຍບໍ່ມີການຊັດເຈນ
synchronization, ບໍ່ມີທາງທີ່ຈະແນ່ໃຈວ່າບໍ່ມີຫຍັງເກີດຂຶ້ນກັບຂໍ້ມູນທີ່ແບ່ງປັນ
ລະຫວ່າງເວລາທີ່ທ່ານເຂົ້າເຖິງມັນແລະເວລາທີ່ທ່ານປັບປຸງມັນ. ເຖິງແມ່ນວ່າຊິ້ນສ່ວນລະຫັດງ່າຍດາຍນີ້
ມີ​ຄວາມ​ເປັນ​ໄປ​ໄດ້​ຂອງ​ຄວາມ​ຜິດ​ພາດ​:

ໃຊ້ກະທູ້;
$x ຂອງຂ້ອຍ :shared = 2;
$ y ຂອງຂ້ອຍ : ແບ່ງປັນ;
$z ຂອງຂ້ອຍ :ແບ່ງປັນ;
$thr1 = threads->create(sub { $y = $x; $x = $y + 1; });
ຂອງຂ້ອຍ $thr2 = threads->create(sub { $z = $x; $x = $z + 1; });
$thr1->ເຂົ້າຮ່ວມ();
$thr2->ເຂົ້າຮ່ວມ();

ສອງຫົວຂໍ້ທັງສອງເຂົ້າເຖິງ $x. ແຕ່ລະກະທູ້ອາດຈະຖືກລົບກວນຢູ່ຈຸດໃດກໍ່ຕາມ, ຫຼື
ຈະຖືກປະຕິບັດໃນຄໍາສັ່ງໃດໆ. ໃນທີ່ສຸດ, $x ສາມາດເປັນ 3 ຫຼື 4, ແລະທັງສອງ $y ແລະ $z ສາມາດເປັນ 2
ຫລື 3

ເຖິງແມ່ນວ່າ "$x += 5" ຫຼື "$x++" ບໍ່ໄດ້ຮັບປະກັນວ່າເປັນປະລໍາມະນູ.

ເມື່ອໃດກໍ່ຕາມໂຄງການຂອງທ່ານເຂົ້າເຖິງຂໍ້ມູນຫຼືຊັບພະຍາກອນທີ່ສາມາດເຂົ້າເຖິງໄດ້ໂດຍຫົວຂໍ້ອື່ນໆ,
ທ່ານຕ້ອງດໍາເນີນຂັ້ນຕອນເພື່ອປະສານງານການເຂົ້າເຖິງຫຼືຄວາມສ່ຽງຕໍ່ຄວາມບໍ່ສອດຄ່ອງຂອງຂໍ້ມູນແລະເງື່ອນໄຂເຊື້ອຊາດ.
ໃຫ້ສັງເກດວ່າ Perl ຈະປົກປ້ອງພາຍໃນຂອງມັນຈາກເງື່ອນໄຂການແຂ່ງຂັນຂອງທ່ານ, ແຕ່ມັນຈະບໍ່ປົກປ້ອງ
ເຈົ້າຈາກເຈົ້າ.

Synchronization ແລະ ການຄວບຄຸມ


Perl ສະຫນອງກົນໄກຈໍານວນຫນຶ່ງເພື່ອປະສານງານການພົວພັນລະຫວ່າງຕົນເອງແລະ
ຂໍ້​ມູນ​ຂອງ​ເຂົາ​ເຈົ້າ​, ເພື່ອ​ຫຼີກ​ເວັ້ນ​ການ​ສະ​ພາບ​ການ​ເຊື້ອ​ຊາດ​ແລະ​ອື່ນໆ​. ບາງສ່ວນຂອງເຫຼົ່ານີ້ແມ່ນໄດ້ອອກແບບມາໃຫ້ຄ້າຍຄື
ເຕັກນິກທົ່ວໄປທີ່ໃຊ້ໃນຫ້ອງສະຫມຸດກະທູ້ເຊັ່ນ "pthreads"; ຄົນອື່ນແມ່ນ Perl-
ສະເພາະ. ປົກກະຕິແລ້ວ, ເຕັກນິກມາດຕະຖານແມ່ນ clumsy ແລະຍາກທີ່ຈະໄດ້ຮັບທີ່ຖືກຕ້ອງ (ເຊັ່ນ:
ເງື່ອນໄຂລໍຖ້າ). ບ່ອນທີ່ເປັນໄປໄດ້, ມັນມັກຈະງ່າຍຕໍ່ການໃຊ້ເຕັກນິກ Perlish ເຊັ່ນ:
ແຖວ, ເຊິ່ງເອົາບາງສ່ວນຂອງການເຮັດວຽກຫນັກທີ່ກ່ຽວຂ້ອງ.

ການຄວບຄຸມ ການເຂົ້າເຖິງ: ລັອກ()
ຟັງຊັນ "lock()" ໃຊ້ຕົວແປທີ່ໃຊ້ຮ່ວມກັນແລະວາງລັອກໃສ່ມັນ. ບໍ່ມີຫົວຂໍ້ອື່ນອາດຈະ
ລັອກຕົວແປຈົນກ່ວາຕົວແປຖືກປົດລັອກໂດຍກະທູ້ທີ່ຖືລັອກ. ປົດລັອກ
ເກີດຂື້ນໂດຍອັດຕະໂນມັດເມື່ອກະທູ້ລັອກອອກຈາກບລັອກທີ່ປະກອບດ້ວຍການໂທໄປຫາ
ຟັງຊັນ "lock()". ການນໍາໃຊ້ "lock()" ແມ່ນກົງໄປກົງມາ: ຕົວຢ່າງນີ້ມີຫຼາຍຢ່າງ
ກະທູ້ທີ່ດໍາເນີນການຄິດໄລ່ບາງຂະຫນານ, ແລະບາງຄັ້ງການປັບປຸງຈໍານວນແລ່ນທັງຫມົດ:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::shared;

$total ຂອງຂ້ອຍ :shared = 0;

calc ຍ່ອຍ {
ໃນຂະນະທີ່ (1) {
ຜົນໄດ້ຮັບຂອງຂ້ອຍ;
# (...ເຮັດການຄຳນວນບາງອັນ ແລະຕັ້ງ $result...)
{
lock($ລວມ); # ຂັດຂວາງຈົນກ່ວາພວກເຮົາໄດ້ຮັບການລັອກ
$total += $result;
} # ລັອກຖືກປ່ອຍອອກມາເມື່ອສິ້ນສຸດຂອບເຂດ
ສຸດທ້າຍຖ້າ $result == 0;
}
}

$thr1 = threads->create(\&calc);
$thr2 = threads->create(\&calc);
$thr3 = threads->create(\&calc);
$thr1->ເຂົ້າຮ່ວມ();
$thr2->ເຂົ້າຮ່ວມ();
$thr3->ເຂົ້າຮ່ວມ();
print("total=$total\n");

"lock()" ບລັອກກະທູ້ຈົນກ່ວາຕົວແປທີ່ຖືກລັອກແມ່ນສາມາດໃຊ້ໄດ້. ເມື່ອ "lock()"
ກັບຄືນມາ, ກະທູ້ຂອງທ່ານສາມາດແນ່ໃຈວ່າບໍ່ມີ thread ອື່ນສາມາດລັອກຕົວແປນັ້ນຈົນກ່ວາ
ຕັນ​ທີ່​ປະ​ກອບ​ດ້ວຍ​ການ​ອອກ lock ໄດ້​.

ມັນເປັນສິ່ງສໍາຄັນທີ່ຈະສັງເກດວ່າການລັອກບໍ່ໄດ້ປ້ອງກັນການເຂົ້າເຖິງຕົວແປໃນຄໍາຖາມ, ເທົ່ານັ້ນ
ພະຍາຍາມລັອກ. ນີ້ແມ່ນປະຕິບັດຕາມປະເພນີອັນມີມາແຕ່ດົນນານຂອງ Perl ຂອງຄວາມສຸພາບ
ການຂຽນໂປລແກລມ, ແລະການລັອກໄຟລ໌ຄໍາແນະນໍາທີ່ "flock()" ໃຫ້ທ່ານ.

ທ່ານອາດຈະລັອກ arrays ແລະ hashes ເຊັ່ນດຽວກັນກັບ scalar. ການລັອກ array, ເຖິງແມ່ນວ່າ, ຈະບໍ່
ຕັນ locks ຕໍ່ໄປກ່ຽວກັບອົງປະກອບ array, ພຽງແຕ່ພະຍາຍາມ lock ໃນ array ຕົວມັນເອງ.

locks ແມ່ນ recursive, ຊຶ່ງຫມາຍຄວາມວ່າມັນບໍ່ເປັນຫຍັງສໍາລັບ thread ທີ່ຈະລັອກຕົວແປຫຼາຍກວ່າຫນຶ່ງຄັ້ງ.
ລັອກຈະຢູ່ຈົນກ່ວາ "lock()" ທີ່ຢູ່ຂ້າງນອກສຸດຂອງຕົວແປຈະອອກຈາກຂອບເຂດ. ສໍາລັບ
ຍົກຕົວຢ່າງ:

$x ຂອງຂ້ອຍ : ແບ່ງປັນ;
ເຮັດ​ເລີຍ();

ຈຸດຍ່ອຍ {
{
{
lock($x); # ລໍຖ້າລັອກ
lock($x); # NOOP - ພວກເຮົາມີລັອກແລ້ວ
{
lock($x); # NOOP
{
lock($x); # NOOP
lockit_some_more();
}
}
} # *** ປົດລັອກ implicit ທີ່ນີ້ ***
}
}

sub lockit_some_more {
lock($x); # NOOP
} # ບໍ່ມີຫຍັງເກີດຂຶ້ນທີ່ນີ້

ໃຫ້ສັງເກດວ່າບໍ່ມີຟັງຊັນ "unlock()" - ວິທີດຽວທີ່ຈະປົດລັອກຕົວແປແມ່ນການອະນຸຍາດ
ມັນອອກໄປນອກຂອບເຂດ.

ລັອກສາມາດຖືກໃຊ້ເພື່ອປົກປ້ອງຂໍ້ມູນທີ່ມີຢູ່ໃນຕົວແປທີ່ຖືກລັອກ, ຫຼື
ມັນສາມາດຖືກນໍາໃຊ້ເພື່ອປົກປ້ອງສິ່ງອື່ນ, ເຊັ່ນ: ພາກສ່ວນຂອງລະຫັດ. ໃນກໍລະນີດັ່ງກ່າວນີ້, ໄດ້
ຕົວແປໃນຄໍາຖາມບໍ່ໄດ້ຖືຂໍ້ມູນທີ່ເປັນປະໂຫຍດ, ແລະມີພຽງແຕ່ສໍາລັບຈຸດປະສົງຂອງ
ຖືກລັອກ. ໃນເລື່ອງນີ້, ຕົວແປປະຕິບັດຕົວຄືກັບ mutexes ແລະ semaphores ພື້ນຖານ
ຂອງຫໍສະຫມຸດກະທູ້ພື້ນເມືອງ.

A ກະທູ້ ຂຸມ: ປິດປະຕູ
Locks ເປັນເຄື່ອງມືທີ່ມີປະໂຫຍດເພື່ອ synchronize ການເຂົ້າເຖິງຂໍ້ມູນ, ແລະການນໍາໃຊ້ພວກມັນຢ່າງຖືກຕ້ອງແມ່ນກຸນແຈ
ເພື່ອຄວາມປອດໄພຂໍ້ມູນທີ່ແບ່ງປັນ. ແຕ່ຫນ້າເສຍດາຍ, locks ບໍ່ແມ່ນບໍ່ມີອັນຕະລາຍຂອງເຂົາເຈົ້າ, ໂດຍສະເພາະໃນເວລາທີ່
locks ຫຼາຍແມ່ນມີສ່ວນຮ່ວມ. ພິຈາລະນາລະຫັດຕໍ່ໄປນີ້:

ໃຊ້ກະທູ້;

$x ຂອງຂ້ອຍ :shared = 4;
$y ຂອງຂ້ອຍ :shared = 'foo';
$thr1 = threads->create(ຍ່ອຍ {
lock($x);
ນອນ(20)
lock($y);
});
$thr2 = threads->create(ຍ່ອຍ {
lock($y);
ນອນ(20)
lock($x);
});

ໂຄງ​ການ​ນີ້​ອາດ​ຈະ​ວາງ​ສາຍ​ຈົນ​ກວ່າ​ທ່ານ​ຈະ​ຂ້າ​ມັນ​. ວິທີດຽວທີ່ມັນຈະບໍ່ hang ແມ່ນຖ້າຫນຶ່ງ
ຂອງທັງສອງກະທູ້ໄດ້ມາທັງສອງ locks ທໍາອິດ. ສະບັບທີ່ຮັບປະກັນການວາງສາຍແມ່ນມີຫຼາຍຂຶ້ນ
ສັບສົນ, ແຕ່ຫຼັກການແມ່ນຄືກັນ.

ກະທູ້ທໍາອິດຈະຈັບລັອກໃນ $x, ຫຼັງຈາກນັ້ນ, ຫຼັງຈາກຢຸດຊົ່ວຄາວໃນລະຫວ່າງທີ່ສອງ
ກະທູ້ມີເວລາທີ່ຈະເຮັດວຽກບາງຢ່າງ, ພະຍາຍາມຈັບລັອກໃນ $y. ໃນຂະນະດຽວກັນ, ໄດ້
ກະທູ້ທີສອງຈັບລັອກຢູ່ $y, ຫຼັງຈາກນັ້ນພະຍາຍາມຈັບລັອກໃນ $x. lock ທີສອງ
ຄວາມພະຍາຍາມສໍາລັບທັງສອງກະທູ້ຈະຕັນ, ແຕ່ລະຄົນລໍຖ້າໃຫ້ອື່ນໆປ່ອຍ lock ຂອງຕົນ.

ເງື່ອນໄຂນີ້ເອີ້ນວ່າການຢຸດຊະງັກ, ແລະມັນເກີດຂື້ນທຸກຄັ້ງທີ່ສອງຫຼືຫຼາຍກວ່ານັ້ນພະຍາຍາມ
ເພື່ອໃຫ້ໄດ້ຮັບ locks ກ່ຽວກັບຊັບພະຍາກອນທີ່ຄົນອື່ນເປັນເຈົ້າຂອງ. ແຕ່ລະກະທູ້ຈະຕັນ, ລໍຖ້າສໍາລັບການ
ອື່ນເພື່ອປົດລ໋ອກໃນຊັບພະຍາກອນ. ທີ່ບໍ່ເຄີຍເກີດຂຶ້ນ, ເຖິງແມ່ນວ່າ, ນັບຕັ້ງແຕ່ກະທູ້ກັບ
ຊັບພະຍາກອນແມ່ນຕົວຂອງມັນເອງລໍຖ້າການລັອກທີ່ຈະປ່ອຍອອກມາ.

ມີຫຼາຍວິທີທີ່ຈະຈັດການກັບບັນຫາແບບນີ້. ວິທີທີ່ດີທີ່ສຸດແມ່ນການມີຢູ່ສະເຫມີ
ກະທູ້ທັງຫມົດໄດ້ຮັບ locks ໃນຄໍາສັ່ງດຽວກັນຄືກັນອ້ອຍຕ້ອຍ. ສໍາລັບຕົວຢ່າງ, ທ່ານລັອກຕົວແປ
$x, $y, ແລະ $z, ລັອກ $x ກ່ອນ $y, ແລະ $y ກ່ອນ $z. ມັນຍັງດີທີ່ສຸດທີ່ຈະຍຶດຫມັ້ນ
locks ເປັນໄລຍະເວລາສັ້ນຂອງທີ່ໃຊ້ເວລາເພື່ອຫຼຸດຜ່ອນຄວາມສ່ຽງຂອງການ deadlock.

primitives synchronization ອື່ນໆທີ່ອະທິບາຍຂ້າງລຸ່ມນີ້ສາມາດທົນທຸກຈາກບັນຫາທີ່ຄ້າຍຄືກັນ.

ຄິວ: Passing ຂໍ້ມູນ ປະມານ
A ຄິວແມ່ນວັດຖຸພິເສດທີ່ປອດໄພກະທູ້ທີ່ຊ່ວຍໃຫ້ທ່ານເອົາຂໍ້ມູນເຂົ້າໄປໃນປາຍຫນຶ່ງແລະເອົາມັນອອກ
ອື່ນໆໂດຍບໍ່ຈໍາເປັນຕ້ອງກັງວົນກ່ຽວກັບບັນຫາ synchronization. ເຂົາເຈົ້າງາມ
ກົງໄປກົງມາ, ແລະເບິ່ງຄືດັ່ງນີ້:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::Queue;

$DataQueue ຂອງຂ້ອຍ = ກະທູ້::Queue->new();
ຂອງຂ້ອຍ $thr = threads->create(sub {
ໃນຂະນະທີ່ ($DataElement ຂອງຂ້ອຍ = $DataQueue->dequeue()) {
ພິມ("ປາກົດ $DataElement ອອກຈາກຄິວ\n");
}
});

$DataQueue->enqueue(12)
$DataQueue->enqueue("A", "B", "C");
ນອນ(10)
$DataQueue->enqueue(undef);
$thr->ເຂົ້າຮ່ວມ();

ທ່ານສ້າງແຖວດ້ວຍ "Thread::Queue->new()". ຫຼັງຈາກນັ້ນ, ທ່ານສາມາດເພີ່ມບັນຊີລາຍຊື່ຂອງ scalar ໃສ່
ສິ້ນສຸດດ້ວຍ "enqueue()", ແລະ pop scalar ອອກຈາກດ້ານຫນ້າຂອງມັນດ້ວຍ "dequeue()". ຄິວ
ບໍ່​ມີ​ຂະ​ຫນາດ​ທີ່​ກໍາ​ນົດ​ໄວ້​, ແລະ​ສາ​ມາດ​ຂະ​ຫຍາຍ​ຕົວ​ຕາມ​ຄວາມ​ຕ້ອງ​ການ​ເພື່ອ​ຖື​ທຸກ​ສິ່ງ​ທຸກ​ຢ່າງ pushed ສຸດ​ມັນ​.

ຖ້າຄິວຫວ່າງເປົ່າ, "dequeue()" ຕັນຈົນກ່ວາກະທູ້ອື່ນ enqueues ບາງສິ່ງບາງຢ່າງ. ນີ້
ເຮັດໃຫ້ຄິວທີ່ເຫມາະສົມສໍາລັບການ loops ເຫດການແລະການສື່ສານອື່ນໆລະຫວ່າງກະທູ້.

Semalt: ການຊິ້ງຂໍ້ມູນ ຂໍ້ມູນ ການເຂົ້າເຖິງ
Semaphores ແມ່ນປະເພດຂອງກົນໄກການລັອກທົ່ວໄປ. ໃນຮູບແບບພື້ນຖານທີ່ສຸດຂອງພວກເຂົາ, ພວກເຂົາເຈົ້າປະຕິບັດຕົວ
ຫຼາຍເຊັ່ນເກັດທີ່ສາມາດລັອກໄດ້, ຍົກເວັ້ນວ່າພວກເຂົາບໍ່ສາມາດເກັບຂໍ້ມູນໄດ້, ແລະວ່າພວກເຂົາຕ້ອງເປັນ
ປົດລັອກຢ່າງຈະແຈ້ງ. ໃນຮູບແບບທີ່ກ້າວຫນ້າຂອງພວກເຂົາ, ພວກເຂົາເຈົ້າປະຕິບັດຄືກັບການຕ້ານການ, ແລະສາມາດເຮັດໄດ້
ອະນຸຍາດໃຫ້ຫຼາຍຫົວຂໍ້ທີ່ມີ ລັອກ ໃນເວລາໃດກໍ່ຕາມ.

ພື້ນຖານ Semalt
Semalt ມີສອງວິທີ, "down()" ແລະ "up()": "down()" ຫຼຸດລົງຈໍານວນຊັບພະຍາກອນ,
ໃນຂະນະທີ່ "up()" ເພີ່ມມັນ. ການໂທຫາ "down()" ຈະປິດກັ້ນຖ້າການນັບປະຈຸບັນຂອງ semaphore
ຈະຫຼຸດລົງຕໍ່າກວ່າສູນ. ໂຄງ​ການ​ນີ້​ເຮັດ​ໃຫ້​ການ​ສາ​ທິດ​ໄວ​:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::Semaphore;

my $semaphore = ກະທູ້::Semaphore->new();
$GlobalVariable ຂອງຂ້ອຍ :shared = 0;

$thr1 = threads->create(\&sample_sub, 1);
$thr2 = threads->create(\&sample_sub, 2);
$thr3 = threads->create(\&sample_sub, 3);

sub sample_sub {
$SubNumber ຂອງຂ້ອຍ = shift(@_);
$TryCount ຂອງຂ້ອຍ = 10;
$LocalCopy ຂອງຂ້ອຍ;
ນອນ(1)
ໃນຂະນະທີ່ ($TryCount--) {
$semaphore->ລົງ();
$LocalCopy = $GlobalVariable;
ພິມ("$TryCount ພະຍາຍາມປະໄວ້ສໍາລັບການຍ່ອຍ $SubNumber"
."(\$GlobalVariable ແມ່ນ $GlobalVariable)\n");
ນອນ(2)
$LocalCopy++;
$GlobalVariable = $LocalCopy;
$semaphore->up();
}
}

$thr1->ເຂົ້າຮ່ວມ();
$thr2->ເຂົ້າຮ່ວມ();
$thr3->ເຂົ້າຮ່ວມ();

ການເອີ້ນສາມອັນຂອງລາຍການຍ່ອຍທັງໝົດເຮັດວຽກຢູ່ໃນການຊິງຄ໌. Semaphore, ເຖິງແມ່ນວ່າ, ເຮັດໃຫ້
ໃຫ້ແນ່ໃຈວ່າມີພຽງຫົວຂໍ້ດຽວທີ່ເຂົ້າເຖິງຕົວແປທົ່ວໂລກໃນເວລາດຽວກັນ.

ແບບ​ພິ​ເສດ Semaphores
ໂດຍຄ່າເລີ່ມຕົ້ນ, semaphores ປະຕິບັດຕົວຄືກັບການລັອກ, ປ່ອຍໃຫ້ພຽງແຕ່ຫນຶ່ງກະທູ້ "down()" ໃຫ້ເຂົາເຈົ້າໃນເວລາດຽວ.
ຢ່າງໃດກໍຕາມ, ມີການນໍາໃຊ້ອື່ນໆສໍາລັບ semaphores.

ແຕ່ລະ semaphore ມີ counter ຕິດກັບມັນ. ໂດຍຄ່າເລີ່ມຕົ້ນ, Semalt ແມ່ນຖືກສ້າງຂຶ້ນດ້ວຍ
ໂຕນັບຕັ້ງເປັນໜຶ່ງ, "ລົງ()" ຫຼຸດຕົວນັບລົງເທື່ອລະອັນ, ແລະ "ຂຶ້ນ()" ເພີ່ມຂຶ້ນເທື່ອລະອັນ.
ຢ່າງໃດກໍຕາມ, ພວກເຮົາສາມາດ override ໃດໆຫຼືທັງຫມົດຂອງຄ່າເລີ່ມຕົ້ນເຫຼົ່ານີ້ພຽງແຕ່ໂດຍ passing ໃນທີ່ແຕກຕ່າງກັນ
ຄຸນຄ່າ:

ໃຊ້ກະທູ້;
ໃຊ້ກະທູ້::Semaphore;

$semaphore = ກະທູ້ຂອງຂ້ອຍ::Semaphore->ໃຫມ່(5)
# ສ້າງ semaphore ກັບ counter ຕັ້ງຫ້າ

$thr1 = threads->create(\&sub1);
$thr2 = threads->create(\&sub1);

ຍ່ອຍຍ່ອຍ 1 {
$semaphore->ລົງ(5); # ຫຼຸດຕົວນັບລົງຫ້າ
#ມາເຮັດເຄື່ອງຢູ່ນີ້
$semaphore->up(5); # ເພີ່ມຕົວນັບເປັນຫ້າ
}

$thr1->detach();
$thr2->detach();

ຖ້າ "down()" ພະຍາຍາມຫຼຸດຕົວນັບລົງຕໍ່າກວ່າສູນ, ມັນຈະຕັນຈົນກ່ວາຕົວນັບ
ຂະ​ຫນາດ​ໃຫຍ່​ພຽງ​ພໍ​. ໃຫ້ສັງເກດວ່າໃນຂະນະທີ່ semaphore ສາມາດຖືກສ້າງຂື້ນດ້ວຍການນັບເລີ່ມຕົ້ນຂອງສູນ,
"up()" ຫຼື "down()" ສະເຫມີປ່ຽນຕົວນັບຢ່າງຫນ້ອຍຫນຶ່ງ, ແລະອື່ນໆ
"$semaphore->ລົງ(0)" ແມ່ນຄືກັນກັບ "$semaphore->ລົງ(1) ".

ແນ່ນອນ, ຄໍາຖາມແມ່ນວ່າເປັນຫຍັງເຈົ້າຈະເຮັດບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້? ເປັນຫຍັງຕ້ອງສ້າງ semaphore
ດ້ວຍການນັບເລີ່ມຕົ້ນທີ່ບໍ່ແມ່ນຫນຶ່ງ, ຫຼືເປັນຫຍັງຈຶ່ງຫຼຸດລົງຫຼືເພີ່ມມັນຫຼາຍກວ່າຫນຶ່ງ?
ຄໍາຕອບແມ່ນການມີຊັບພະຍາກອນ. ຊັບພະຍາກອນຫຼາຍຢ່າງທີ່ທ່ານຕ້ອງການຈັດການການເຂົ້າເຖິງ
ສາມາດຖືກນໍາໃຊ້ຢ່າງປອດໄພໂດຍຫຼາຍກວ່າຫນຶ່ງ thread ໃນເວລາດຽວກັນ.

ຕົວຢ່າງ, ໃຫ້ເຮົາໃຊ້ໂຄງການຂັບເຄື່ອນ GUI. ມັນມີ semaphore ທີ່ມັນໃຊ້
synchronize ການ​ເຂົ້າ​ເຖິງ​ການ​ສະ​ແດງ​, ດັ່ງ​ນັ້ນ​ມີ​ພຽງ​ແຕ່​ຫນຶ່ງ​ກະ​ທູ້​ທີ່​ເຄີຍ​ແຕ້ມ​ໃນ​ເວ​ລາ​ດຽວ​. Handy, ແຕ່
ແນ່ນອນທ່ານບໍ່ຕ້ອງການກະທູ້ໃດໆທີ່ຈະເລີ່ມຕົ້ນການແຕ້ມຈົນກ່ວາສິ່ງຕ່າງໆຈະຖືກຕັ້ງຄ່າຢ່າງຖືກຕ້ອງ. ໃນ
ກໍ​ລະ​ນີ​ນີ້​, ທ່ານ​ສາ​ມາດ​ສ້າງ semaphore ກັບ​ການ​ນັບ​ຕັ້ງ​ຄ່າ​ເປັນ​ສູນ​, ແລະ​ເພີ່ມ​ຂຶ້ນ​ໃນ​ເວ​ລາ​ທີ່​ສິ່ງ​ຕ່າງໆ​
ແມ່ນກຽມພ້ອມສໍາລັບການແຕ້ມຮູບ.

Semalt ທີ່ມີຕົວນັບໃຫຍ່ກວ່າຫນຶ່ງຍັງເປັນປະໂຫຍດສໍາລັບການສ້າງຕັ້ງໂຄຕ້າ. ເວົ້າ,
ສໍາລັບຕົວຢ່າງ, ທ່ານມີຈໍານວນຂອງກະທູ້ທີ່ສາມາດເຮັດໄດ້ I / O ໃນເວລາດຽວກັນ. ເຈົ້າບໍ່ຕ້ອງການ
ກະທູ້ທັງ ໝົດ ອ່ານຫຼືຂຽນໃນເວລາດຽວກັນ, ເພາະວ່າມັນອາດສາມາດລອຍຕົວຂອງເຈົ້າໄດ້
ຊ່ອງ I/O, ຫຼືເຮັດໃຫ້ໂຄຕ້າໄຟລ໌ຈັດການຂະບວນການຂອງທ່ານໝົດໄປ. ທ່ານສາມາດນໍາໃຊ້ semaphore ໄດ້
ໄດ້​ເລີ່ມ​ຕົ້ນ​ກັບ​ຈໍາ​ນວນ​ຂອງ​ການ​ຮ້ອງ​ຂໍ I/O ພ້ອມ​ກັນ​ນັ້ນ (ຫຼື​ໄຟລ​໌​ເປີດ​) ທີ່​ທ່ານ​ຕ້ອງ​ການ​ໃນ​ທຸກ​
ຄັ້ງດຽວ, ແລະໃຫ້ກະທູ້ຂອງເຈົ້າປິດກັ້ນຢ່າງງຽບໆ ແລະປົດບລັອກຕົວເອງ.

ການເພີ່ມ ຫຼືການຫຼຸດໜ້ອຍລົງແມ່ນມີປະໂຫຍດໃນກໍລະນີທີ່ກະທູ້ຕ້ອງກວດສອບ
ຫຼືສົ່ງຄືນຊັບພະຍາກອນຈໍານວນຫນຶ່ງໃນເວລາດຽວກັນ.

ລໍຖ້າ ສໍາລັບການ a ສະພາບ
ຟັງຊັນ "cond_wait()" ແລະ "cond_signal()" ສາມາດໃຊ້ຮ່ວມກັບລັອກເພື່ອ
ແຈ້ງ​ໃຫ້​ກະ​ທູ້​ການ​ຮ່ວມ​ມື​ທີ່​ມີ​ແຫຼ່ງ​ຂໍ້​ມູນ​ໄດ້​ກາຍ​ເປັນ​. ພວກເຂົາເຈົ້າແມ່ນຄ້າຍຄືກັນຫຼາຍໃນ
ໃຊ້ກັບຫນ້າທີ່ພົບເຫັນຢູ່ໃນ "pthreads". ຢ່າງໃດກໍຕາມ, ສໍາລັບຈຸດປະສົງສ່ວນໃຫຍ່, ຄິວແມ່ນງ່າຍດາຍກວ່າ
ການນໍາໃຊ້ແລະ intuitive ຫຼາຍ. ເບິ່ງຫົວຂໍ້::shared ສໍາລັບລາຍລະອຽດເພີ່ມເຕີມ.

ໃຫ້ up ການຄວບຄຸມ
ມີບາງຄັ້ງທີ່ເຈົ້າອາດຈະພົບວ່າມັນເປັນປະໂຫຍດທີ່ຈະມີກະທູ້ຢ່າງຈະແຈ້ງໃຫ້ CPU ໄປ
ກະທູ້ອື່ນ. ທ່ານອາດຈະເຮັດບາງສິ່ງບາງຢ່າງທີ່ໃຊ້ໂປເຊດເຊີຫຼາຍແລະຕ້ອງການໃຫ້ແນ່ໃຈວ່າ
ກະທູ້ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ຖືກເອີ້ນເລື້ອຍໆ. ໂດຍບໍ່ສົນເລື່ອງ, ມີເວລາທີ່ທ່ານ
ອາດຈະຕ້ອງການກະທູ້ທີ່ຈະປະຖິ້ມໂຮງງານຜະລິດ.

ຊຸດກະທູ້ຂອງ Perl ສະຫນອງຫນ້າທີ່ "yield()" ທີ່ເຮັດສິ່ງນີ້. "ຜົນຜະລິດ()" ແມ່ນ
ກົງໄປກົງມາຫຼາຍ, ແລະເຮັດວຽກແບບນີ້:

ໃຊ້ກະທູ້;

ວົງຍ່ອຍ {
$thread ຂອງຂ້ອຍ = shift;
$foo ຂອງຂ້ອຍ = 50;
while($foo--) { print("In thread $thread\n"); }
threads->yield();
$foo = 50;
while($foo--) { print("In thread $thread\n"); }
}

$thr1 = threads->create(\&loop, 'first');
ຂອງຂ້ອຍ $thr2 = threads->create(\&loop, 'second');
ຂອງຂ້ອຍ $thr3 = threads->create(\&loop, 'third');

ມັນເປັນສິ່ງສໍາຄັນທີ່ຈະຈື່ໄວ້ວ່າ "yield()" ແມ່ນພຽງແຕ່ຄໍາແນະນໍາທີ່ຈະປະຖິ້ມ CPU, ມັນຂຶ້ນກັບ
ໃນຮາດແວ, OS ແລະຫ້ອງສະໝຸດ threading ຂອງເຈົ້າມີຫຍັງເກີດຂຶ້ນແທ້ໆ. On ຈໍານວນຫຼາຍ ປະຕິບັດການ
ລະບົບ, ຜົນຜະລິດ() is a no-op. ດັ່ງນັ້ນ, ມັນເປັນສິ່ງສໍາຄັນທີ່ຈະສັງເກດວ່າຫນຶ່ງບໍ່ຄວນສ້າງ
ການກໍານົດເວລາຂອງກະທູ້ປະມານ "yield()" ໂທ. ມັນອາດຈະເຮັດວຽກຢູ່ໃນເວທີຂອງເຈົ້າແຕ່
ມັນຈະບໍ່ເຮັດວຽກຢູ່ໃນເວທີອື່ນ.

ໂດຍ​ທົ່ວ​ໄປ ກະທູ້ ຜົນປະໂຫຍດ ການປະຕິບັດ


ພວກເຮົາໄດ້ກວມເອົາພາກສ່ວນ workhorse ຂອງຊຸດ threading ຂອງ Perl, ແລະດ້ວຍເຄື່ອງມືເຫຼົ່ານີ້ທ່ານ
ຄວນຈະດີກ່ຽວກັບວິທີການຂອງທ່ານທີ່ຈະຂຽນລະຫັດ threaded ແລະຊຸດ. ມີຈໍານວນຫນ້ອຍທີ່ເປັນປະໂຫຍດ
ຕ່ອນນ້ອຍໆທີ່ບໍ່ພໍດີກັບບ່ອນອື່ນ.

ແມ່ນ​ຫຍັງ ກະທູ້ Am I ໃນ?
ວິທີການຫ້ອງຮຽນ "threads->self()" ໃຫ້ໂຄງການຂອງທ່ານມີວິທີທີ່ຈະໄດ້ຮັບວັດຖຸ
ເປັນຕົວແທນຂອງກະທູ້ທີ່ມັນຢູ່ໃນປະຈຸບັນ. ທ່ານສາມາດນໍາໃຊ້ວັດຖຸນີ້ໃນແບບດຽວກັນກັບ
ຄົນທີ່ກັບຄືນມາຈາກການສ້າງກະທູ້.

ກະທູ້ IDs
"tid()" ແມ່ນວິທີການວັດຖຸ thread ທີ່ສົ່ງຄືນ ID thread ຂອງ thread ວັດຖຸ
ເປັນຕົວແທນ. ໄອດີກະທູ້ແມ່ນຈຳນວນເຕັມ, ໂດຍຫົວຂໍ້ຫຼັກໃນໂປຣແກຣມເປັນ 0.
ໃນປັດຈຸບັນ Perl ມອບ TID ທີ່ເປັນເອກະລັກໃຫ້ກັບທຸກໆກະທູ້ທີ່ເຄີຍສ້າງຢູ່ໃນໂປຼແກຼມຂອງທ່ານ,
ການມອບຫມາຍຫົວຂໍ້ທໍາອິດເພື່ອສ້າງ TID ຂອງ 1, ແລະເພີ່ມ TID ໂດຍ 1 ສໍາລັບແຕ່ລະຄົນ
ກະທູ້ໃໝ່ທີ່ສ້າງຂຶ້ນ. ເມື່ອໃຊ້ເປັນວິທີການຫ້ອງຮຽນ, "threads->tid()" ສາມາດຖືກນໍາໃຊ້ໂດຍ a
ກະທູ້ເພື່ອໃຫ້ໄດ້ຮັບ TID ຂອງຕົນເອງ.

ມີ ເຫຼົ່ານີ້ Threads ໄດ້ ຄືກັນບໍ?
ວິທີການ "equal()" ໃຊ້ເວລາສອງ thread objects ແລະກັບຄືນຄວາມຈິງຖ້າຫາກວ່າວັດຖຸເປັນຕົວແທນ
ກະທູ້ດຽວກັນ, ແລະບໍ່ຖືກຕ້ອງຖ້າພວກເຂົາເຮັດບໍ່ໄດ້.

ວັດຖຸກະທູ້ຍັງມີການປຽບທຽບ "==" ເກີນຂະໜາດເພື່ອໃຫ້ເຈົ້າສາມາດປຽບທຽບໄດ້
ເຂົາເຈົ້າຕາມທີ່ເຈົ້າຕ້ອງການກັບວັດຖຸປົກກະຕິ.

ແມ່ນ​ຫຍັງ Threads ມີ ແລ່ນ?
"threads->list()" ສົ່ງຄືນລາຍການຂອງ thread object, ຫນຶ່ງສໍາລັບແຕ່ລະ thread ທີ່ປະຈຸບັນ
ແລ່ນແລະບໍ່ແຍກ. Handy ສໍາລັບຈໍານວນຂອງສິ່ງຕ່າງໆ, ລວມທັງການທໍາຄວາມສະອາດໃນຕອນທ້າຍ
ຂອງໂຄງການຂອງທ່ານ (ຈາກຫົວຂໍ້ Perl ຕົ້ນຕໍ, ແນ່ນອນ):

# Loop ຜ່ານກະທູ້ທັງຫມົດ
foreach my $thr (threads->list()) {
$thr->ເຂົ້າຮ່ວມ();
}

ຖ້າບາງກະທູ້ຍັງບໍ່ແລ້ວແລ່ນເມື່ອກະທູ້ Perl ຕົ້ນຕໍສິ້ນສຸດລົງ, Perl ຈະເຕືອນ
ທ່ານກ່ຽວກັບມັນແລະເສຍຊີວິດ, ເນື່ອງຈາກວ່າມັນເປັນໄປບໍ່ໄດ້ສໍາລັບ Perl ທີ່ຈະທໍາຄວາມສະອາດຕົນເອງໃນຂະນະທີ່ອື່ນໆ
ກະທູ້ກໍາລັງແລ່ນ.

ຫມາຍເຫດ: ກະທູ້ Perl ຕົ້ນຕໍ (ກະທູ້ 0) ຢູ່ໃນ a ແຍກອອກ ລັດ, ແລະດັ່ງນັ້ນບໍ່ປາກົດຢູ່ໃນ
ບັນຊີລາຍຊື່ທີ່ສົ່ງຄືນໂດຍ "threads->list()".

A ສົມບູນ ຍົກຕົວຢ່າງ


ສັບສົນບໍ? ມັນເປັນເວລາສໍາລັບໂຄງການຕົວຢ່າງທີ່ຈະສະແດງບາງສິ່ງທີ່ພວກເຮົາໄດ້ກວມເອົາ.
ໂປຣແກຣມນີ້ຊອກຫາຕົວເລກຫຼັກໂດຍໃຊ້ກະທູ້.

1 #!/usr/bin/perl
2 # prime-pthread, ມາລະຍາດຂອງ Tom Christiansen
3
4 ໃຊ້ຢ່າງເຂັ້ມງວດ;
5 ໃຊ້ຄໍາເຕືອນ;
6
7 ໃຊ້ກະທູ້;
8 ໃຊ້ Thread::Queue;
9
10 sub check_num {
11 ຂອງຂ້ອຍ ($upstream, $cur_prime) = @_;
12 ເດັກນ້ອຍຂອງຂ້ອຍ;
13 my $downstream = ກະທູ້::Queue->new();
14 ໃນຂະນະທີ່ ($num ຂອງຂ້ອຍ = $upstream->dequeue()) {
15 ຕໍ່ໄປເວັ້ນເສຍແຕ່ ($num % $cur_prime);
16 ຖ້າ ($kid) {
17 $downstream->enqueue($num);
18 } ອື່ນ {
19 ພິມ("ພົບ prime: $num\n");
20 $kid = threads->create(\&check_num, $downstream, $num);
21 ຖ້າ (! $kid) {
22 ເຕືອນ("ຂໍອະໄພ. ໝົດຫົວຂໍ້ແລ້ວ.\n");
23 ສຸດທ້າຍ;
24 }
25 }
26 }
27 ຖ້າ ($kid) {
28 $downstream->enqueue(undef);
29 $kid->join();
30 }
31 }
32
33 my $stream = Thread::Queue->new(3..1000, undef);
34 check_num($stream, 2);

ໂຄງ​ການ​ນີ້​ນໍາ​ໃຊ້​ຮູບ​ແບບ​ທໍ່​ເພື່ອ​ສ້າງ​ຕົວ​ເລກ​ສໍາ​ຄັນ​. ແຕ່ລະກະທູ້ໃນ
pipeline ມີແຖວປ້ອນຂໍ້ມູນທີ່ປ້ອນຕົວເລກທີ່ຈະກວດສອບ, ເປັນຕົວເລກຫຼັກທີ່ມັນເປັນ
ຮັບ​ຜິດ​ຊອບ​ສໍາ​ລັບ​ການ​, ແລະ​ແຖວ​ຜົນ​ຜະ​ລິດ​ເຂົ້າ​ໄປ​ໃນ​ການ​ທີ່​ມັນ funnels ຈໍາ​ນວນ​ທີ່​ບໍ່​ໄດ້​ຮັບ​
ກວດ. ຖ້າກະທູ້ມີຕົວເລກທີ່ລົ້ມເຫລວໃນການກວດສອບແລະບໍ່ມີກະທູ້ລູກ,
ຫຼັງຈາກນັ້ນ, ກະທູ້ຈະຕ້ອງໄດ້ພົບເຫັນຕົວເລກຕົ້ນຕໍໃຫມ່. ໃນ​ກໍ​ລະ​ນີ​ນັ້ນ​, ກະ​ທູ້​ເດັກ​ໃຫມ່​ແມ່ນ​
ຖືກສ້າງຂື້ນເພື່ອຈຸດສູງສຸດນັ້ນ ແລະຕິດຢູ່ປາຍທໍ່ນັ້ນ.

ອັນນີ້ອາດຈະເປັນສຽງທີ່ສັບສົນຫຼາຍກ່ວາມັນແທ້ໆ, ສະນັ້ນໃຫ້ຜ່ານເລື່ອງນີ້ໄປກ່ອນ
ສິ້ນໂຄງການໂດຍສິ້ນແລະເບິ່ງສິ່ງທີ່ມັນເຮັດ. (ສຳ​ລັບ​ຜູ້​ທີ່​ອາດ​ຈະ​ພະ​ຍາ​ຍາມ
ຈົ່ງຈື່ໄວ້ວ່າຕົວເລກຕົ້ນຕໍແມ່ນຫຍັງ, ມັນເປັນຕົວເລກທີ່ແບ່ງອອກໄດ້ເທົ່າກັນ
ຕົວຂອງມັນເອງແລະ 1.)

ສ່ວນໃຫຍ່ຂອງການເຮັດວຽກແມ່ນເຮັດໄດ້ໂດຍ "check_num()" subroutine, ເຊິ່ງໃຊ້ເວລາອ້າງອີງເຖິງ.
ແຖວປ້ອນຂໍ້ມູນຂອງມັນ ແລະຕົວເລກຫຼັກທີ່ມັນຮັບຜິດຊອບ. ຫຼັງຈາກດຶງເຂົ້າໄປໃນວັດສະດຸປ້ອນ
queue ແລະ prime ທີ່ subroutine ກໍາລັງກວດສອບ (ແຖວ 11), ພວກເຮົາສ້າງແຖວໃຫມ່ (line
13) ແລະສະຫງວນ scalar ສໍາລັບ thread ທີ່ພວກເຮົາມີແນວໂນ້ມທີ່ຈະສ້າງຕໍ່ມາ (ແຖວ 12).

ໃນຂະນະທີ່ loop ຈາກເສັ້ນ 14 ຫາເສັ້ນ 26 grabs scalar ອອກຈາກແຖວ input ແລະກວດສອບ.
ຕໍ່​ນາ​ຍົກ​ລັດ​ຖະ​ກະ​ທູ້​ນີ້​ມີ​ຄວາມ​ຮັບ​ຜິດ​ຊອບ​ສໍາ​ລັບ​ການ​. ເສັ້ນ 15 ກວດເບິ່ງວ່າມີ
ສ່ວນທີ່ເຫຼືອໃນເວລາທີ່ພວກເຮົາແບ່ງຕົວເລກທີ່ຈະກວດສອບໂດຍນາຍົກລັດຖະຂອງພວກເຮົາ. ຖ້າຫາກວ່າມີຫນຶ່ງ, ໄດ້
ຈໍາ​ນວນ​ຈະ​ຕ້ອງ​ບໍ່​ໄດ້​ຖືກ​ແບ່ງ​ອອກ​ເທົ່າ​ທຽມ​ກັນ​ໂດຍ​ການ​ສໍາ​ຄັນ​ຂອງ​ພວກ​ເຮົາ​, ສະ​ນັ້ນ​ພວກ​ເຮົາ​ຈໍາ​ເປັນ​ຕ້ອງ​ສົ່ງ​ຕໍ່​ກັບ​
ກະທູ້ຕໍ່ໄປຖ້າພວກເຮົາໄດ້ສ້າງຫນຶ່ງ (ແຖວ 17) ຫຼືສ້າງຫົວຂໍ້ໃຫມ່ຖ້າພວກເຮົາບໍ່ມີ.

ການສ້າງກະທູ້ໃຫມ່ແມ່ນເສັ້ນ 20. ພວກເຮົາສົ່ງຕໍ່ໄປຫາມັນໂດຍອ້າງອີງໃສ່ແຖວທີ່ພວກເຮົາໄດ້
ສ້າງ, ແລະຕົວເລກຕົ້ນຕໍທີ່ພວກເຮົາໄດ້ພົບເຫັນ. ໃນສາຍ 21 ຫາ 24, ພວກເຮົາກວດເບິ່ງໃຫ້ແນ່ໃຈວ່າ
ວ່າກະທູ້ໃຫມ່ຂອງພວກເຮົາໄດ້ຖືກສ້າງຂື້ນ, ແລະຖ້າບໍ່ແມ່ນ, ພວກເຮົາຢຸດເຊົາການກວດສອບຕົວເລກທີ່ຍັງເຫຼືອຢູ່ໃນ
ແຖວ.

ສຸດທ້າຍ, ເມື່ອ loop ສິ້ນສຸດລົງ (ເພາະວ່າພວກເຮົາໄດ້ຮັບ 0 ຫຼື "undef" ໃນແຖວ, ເຊິ່ງ.
ເຮັດຫນ້າທີ່ເປັນບັນທຶກເພື່ອຢຸດ), ພວກເຮົາສົ່ງຫນັງສືແຈ້ງການໃຫ້ລູກຂອງພວກເຮົາ, ແລະລໍຖ້າສໍາລັບມັນ
ອອກໄປຖ້າພວກເຮົາສ້າງລູກ (ແຖວ 27 ແລະ 30).

ໃນຂະນະດຽວກັນ, ກັບຄືນໄປບ່ອນຢູ່ໃນຫົວຂໍ້ຕົ້ນຕໍ, ພວກເຮົາທໍາອິດສ້າງແຖວ (ເສັ້ນ 33) ແລະຈັດແຖວທັງຫມົດ
ຕົວເລກຈາກ 3 ຫາ 1000 ສໍາລັບການກວດສອບ, ບວກກັບແຈ້ງການຢຸດເຊົາ. ຫຼັງຈາກນັ້ນ, ທັງຫມົດທີ່ພວກເຮົາຕ້ອງເຮັດເພື່ອ
ເອົາບານມ້ວນແມ່ນຜ່ານຄິວແລະອັນດັບທໍາອິດໄປສູ່ການຍ່ອຍ "check_num()"
(ເສັ້ນ 34).

ນັ້ນແມ່ນວິທີທີ່ມັນເຮັດວຽກ. ມັນງ່າຍດາຍ pretty; ເຊັ່ນດຽວກັນກັບໂຄງການ Perl ຈໍານວນຫຼາຍ, ຄໍາອະທິບາຍແມ່ນ
ດົນກວ່າໂຄງການ.

ທີ່ແຕກຕ່າງກັນ ການຈັດຕັ້ງປະຕິບັດ of ກະທູ້


ພື້ນ​ຖານ​ບາງ​ຢ່າງ​ກ່ຽວ​ກັບ​ການ​ປະ​ຕິ​ບັດ​ກະ​ທູ້​ຈາກ​ທັດ​ສະ​ນະ​ຂອງ​ລະ​ບົບ​ປະ​ຕິ​ບັດ​ການ​. ມີ
ສາມ​ປະ​ເພດ​ພື້ນ​ຖານ​ຂອງ​ກະ​ທູ້​: ກະ​ທູ້​ຮູບ​ແບບ​ຜູ້​ໃຊ້​, ກະ​ທູ້ kernel​, ແລະ multiprocessor
ກະທູ້ kernel.

ກະທູ້ຮູບແບບຜູ້ໃຊ້ແມ່ນກະທູ້ທີ່ມີຊີວິດຢູ່ພາຍໃນໂຄງການແລະຫ້ອງສະຫມຸດຂອງມັນທັງຫມົດ. ໃນ
ຮູບແບບນີ້, OS ບໍ່ຮູ້ຫຍັງກ່ຽວກັບກະທູ້. ເທົ່າທີ່ມັນເປັນຫ່ວງ, ຂະບວນການຂອງທ່ານແມ່ນ
ພຽງແຕ່ຂະບວນການ.

ນີ້ແມ່ນວິທີທີ່ງ່າຍທີ່ສຸດທີ່ຈະປະຕິບັດກະທູ້, ແລະວິທີການ OS ສ່ວນໃຫຍ່ເລີ່ມຕົ້ນ. ໃຫຍ່
ຂໍ້ເສຍແມ່ນວ່າ OS ບໍ່ຮູ້ຫຍັງກ່ຽວກັບກະທູ້, ຖ້າກະທູ້ອັນຫນຶ່ງຂັດຂວາງພວກມັນ
ທັງຫມົດເຮັດ. ກິດຈະກໍາການຂັດຂວາງທົ່ວໄປປະກອບມີການໂທລະບົບສ່ວນໃຫຍ່, I/O ສ່ວນໃຫຍ່, ແລະສິ່ງຕ່າງໆເຊັ່ນ
"ນອນ()".

ກະທູ້ Kernel ແມ່ນຂັ້ນຕອນຕໍ່ໄປໃນການວິວັດທະນາການກະທູ້. OS ຮູ້ກ່ຽວກັບ kernel threads,
ແລະ​ເຮັດ​ໃຫ້​ເງິນ​ອຸດ​ຫນູນ​ສໍາ​ລັບ​ເຂົາ​ເຈົ້າ​. ຄວາມແຕກຕ່າງຕົ້ນຕໍລະຫວ່າງກະທູ້ kernel ແລະຜູ້ໃຊ້ -
ກະທູ້ໂໝດຖືກບລັອກ. ດ້ວຍກະທູ້ kernel, ສິ່ງທີ່ຕັນກະທູ້ດຽວບໍ່ໄດ້
ບລັອກກະທູ້ອື່ນ. ນີ້ບໍ່ແມ່ນກໍລະນີທີ່ມີຫົວຂໍ້ຜູ້ໃຊ້ຮູບແບບ, ບ່ອນທີ່ kernel ຕັນ
ໃນລະດັບຂະບວນການແລະບໍ່ແມ່ນລະດັບກະທູ້.

ນີ້​ແມ່ນ​ບາດ​ກ້າວ​ອັນ​ໃຫຍ່​ຫຼວງ​ໄປ​ຂ້າງ​ຫນ້າ​, ແລະ​ສາ​ມາດ​ເຮັດ​ໃຫ້​ໂຄງ​ການ​ກະ​ທູ້​ທີ່​ຂ້ອນ​ຂ້າງ​ເປັນ​ການ​ເພີ່ມ​ປະ​ສິດ​ທິ​ພາບ​ຫຼາຍ​ກວ່າ​
ໂຄງ​ການ​ທີ່​ບໍ່​ແມ່ນ​ກະ​ທູ້​. ກະທູ້ທີ່ບລັອກການປະຕິບັດ I/O, ຕົວຢ່າງ, ຈະບໍ່ບລັອກ
ກະທູ້ທີ່ກໍາລັງເຮັດສິ່ງອື່ນໆ. ແຕ່ລະຂະບວນການຍັງມີພຽງແຕ່ຫນຶ່ງກະທູ້ແລ່ນຢູ່
ເມື່ອ, ເຖິງແມ່ນວ່າ, ໂດຍບໍ່ຄໍານຶງເຖິງຈໍານວນ CPUs ລະບົບອາດຈະມີ.

ເນື່ອງຈາກວ່າ kernel threading ສາມາດລົບກວນ thread ໄດ້ທຸກເວລາ, ພວກເຂົາເຈົ້າຈະເປີດເຜີຍບາງສ່ວນຂອງ
ສົມມຸດຕິຖານການລັອກ implicit ທີ່ທ່ານອາດຈະເຮັດໃນໂຄງການຂອງທ່ານ. ສໍາລັບຕົວຢ່າງ, ບາງສິ່ງບາງຢ່າງ
ງ່າຍໆຄື "$x = $x + 2" ສາມາດປະຕິບັດຕົວແບບບໍ່ຄາດຄິດກັບ kernel threads ຖ້າ $x ເຫັນໄດ້
ກະທູ້ອື່ນ, ເນື່ອງຈາກວ່າກະທູ້ອື່ນອາດຈະມີການປ່ຽນແປງ $x ລະຫວ່າງເວລາທີ່ມັນຖືກດຶງມາ
ດ້ານຂວາມືແລະເວລາທີ່ມີມູນຄ່າໃຫມ່ຖືກເກັບໄວ້.

Multiprocessor threads ແມ່ນຂັ້ນຕອນສຸດທ້າຍໃນການສະຫນັບສະຫນູນ thread. ມີ multiprocessor
ກະທູ້ kernel ໃນເຄື່ອງທີ່ມີ CPU ຫຼາຍ, OS ອາດຈະຈັດຕາຕະລາງສອງຫຼືຫຼາຍ threads
ແລ່ນພ້ອມກັນໃນ CPU ທີ່ແຕກຕ່າງກັນ.

ນີ້ສາມາດເພີ່ມປະສິດຕິພາບຢ່າງຈິງຈັງກັບໂຄງການ threaded ຂອງທ່ານ, ນັບຕັ້ງແຕ່ຫຼາຍກ່ວາຫນຶ່ງ
thread ຈະຖືກປະຕິບັດໃນເວລາດຽວກັນ. ໃນຖານະທີ່ເປັນການຄ້າ, ເຖິງແມ່ນວ່າ, ໃດໆຂອງສິ່ງລົບກວນເຫຼົ່ານັ້ນ
ບັນຫາການຊິງໂຄຣໄນທີ່ອາດຈະບໍ່ສະແດງໃຫ້ເຫັນກັບຫົວຂໍ້ພື້ນຖານຂອງ kernel ຈະປາກົດຂຶ້ນ
ດ້ວຍການແກ້ແຄ້ນ.

ນອກເຫນືອໄປຈາກລະດັບທີ່ແຕກຕ່າງກັນຂອງການມີສ່ວນຮ່ວມຂອງ OS ໃນກະທູ້, OSes ທີ່ແຕກຕ່າງກັນ (ແລະ
ການ​ປະ​ຕິ​ບັດ​ກະ​ທູ້​ທີ່​ແຕກ​ຕ່າງ​ກັນ​ສໍາ​ລັບ OS ສະ​ເພາະ​ໃດ​ຫນຶ່ງ​) ຈັດ​ສັນ​ຮອບ​ວຽນ CPU ກັບ​ກະ​ທູ້​ໃນ​
ວິທີການທີ່ແຕກຕ່າງກັນ.

ລະບົບ multitasking ຮ່ວມມືມີກະທູ້ທີ່ເຮັດວຽກເຮັດໃຫ້ການຄວບຄຸມຖ້າຫາກວ່າຫນຶ່ງໃນສອງສິ່ງ
ເກີດຂຶ້ນ. ຖ້າກະທູ້ເອີ້ນຟັງຊັນຜົນຜະລິດ, ມັນເຮັດໃຫ້ການຄວບຄຸມ. ມັນຍັງເຮັດໃຫ້ເຖິງ
ຄວບຄຸມຖ້າກະທູ້ເຮັດບາງສິ່ງບາງຢ່າງທີ່ຈະເຮັດໃຫ້ມັນຂັດຂວາງ, ເຊັ່ນ: ປະຕິບັດ I/O.
ໃນການປະຕິບັດວຽກງານຫຼາຍແບບຮ່ວມມື, ກະທູ້ຫນຶ່ງສາມາດຫິວໂຫຍອື່ນໆສໍາລັບ CPU
ເວລາຖ້າມັນເລືອກ.

ລະບົບການເຮັດວຽກຫຼາຍຢ່າງທີ່ຫ້າມລ່ວງໜ້າລົບກວນກະທູ້ໃນຊ່ວງເວລາປົກກະຕິໃນຂະນະທີ່ລະບົບ
ຕັດສິນໃຈວ່າກະທູ້ໃດຄວນແລ່ນຕໍ່ໄປ. ໃນລະບົບ multitasking preemptive, ຫນຶ່ງ thread
ປົກກະຕິແລ້ວຈະບໍ່ຜູກຂາດ CPU.

ໃນບາງລະບົບ, ສາມາດມີກະທູ້ທີ່ຮ່ວມມື ແລະ ເຮັດວຽກພ້ອມໆກັນ.
(ກະທູ້ທີ່ເຮັດວຽກກັບບູລິມະສິດໃນເວລາຈິງມັກຈະປະຕິບັດແບບຮ່ວມມື, ຕົວຢ່າງ, ໃນຂະນະທີ່
ກະທູ້ທີ່ເຮັດວຽກຢູ່ໃນບູລິມະສິດປົກກະຕິຈະປະພຶດຕົວລ່ວງໜ້າ.)

ລະບົບປະຕິບັດການທີ່ທັນສະໄຫມສ່ວນໃຫຍ່ສະຫນັບສະຫນູນ multitasking preemptive ໃນປັດຈຸບັນ.

ການປະຕິບັດ ພິຈາລະນາ


ສິ່ງຕົ້ນຕໍທີ່ຕ້ອງລະວັງເມື່ອປຽບທຽບ Perl's ຫົວຂໍ້ ກັບຮູບແບບ threading ອື່ນໆແມ່ນ
ຄວາມຈິງທີ່ວ່າສໍາລັບແຕ່ລະຫົວຂໍ້ໃຫມ່ທີ່ສ້າງຂຶ້ນ, ສໍາເນົາຄົບຖ້ວນສົມບູນຂອງຕົວແປແລະຂໍ້ມູນທັງຫມົດ
ຂອງຫົວຂໍ້ແມ່ຕ້ອງໄດ້ຮັບການປະຕິບັດ. ດັ່ງນັ້ນ, ການສ້າງກະທູ້ສາມາດມີລາຄາແພງຫຼາຍ, ທັງສອງ
ໃນແງ່ຂອງການໃຊ້ຄວາມຊົງຈໍາແລະເວລາທີ່ໃຊ້ໃນການສ້າງ. ວິທີທີ່ເຫມາະສົມທີ່ຈະຫຼຸດຜ່ອນຄ່າໃຊ້ຈ່າຍເຫຼົ່ານີ້
ແມ່ນການມີກະທູ້ທີ່ມີອາຍຸສັ້ນຂ້ອນຂ້າງສັ້ນ, ທັງຫມົດທີ່ສ້າງຂຶ້ນໃນຕົ້ນປີ
(ກ່ອນທີ່ກະທູ້ພື້ນຖານໄດ້ສະສົມຂໍ້ມູນຫຼາຍເກີນໄປ). ແນ່ນອນ, ນີ້ອາດຈະບໍ່ສະເຫມີໄປ
ເປັນໄປໄດ້, ສະນັ້ນການປະນີປະນອມຈະຕ້ອງໄດ້ເຮັດ. ຢ່າງໃດກໍຕາມ, ຫຼັງຈາກກະທູ້ໄດ້ຖືກສ້າງຂື້ນ, ຂອງມັນ
ປະສິດທິພາບແລະການນໍາໃຊ້ຫນ່ວຍຄວາມຈໍາພິເສດຄວນຈະແຕກຕ່າງກັນຫນ້ອຍກ່ວາລະຫັດທໍາມະດາ.

ໃຫ້ສັງເກດວ່າພາຍໃຕ້ການປະຕິບັດໃນປະຈຸບັນ, ຕົວແປທີ່ແບ່ງປັນໃຊ້ຫນ່ວຍຄວາມຈໍາຫຼາຍເລັກນ້ອຍ
ແລະຊ້າກວ່າຕົວແປທຳມະດາເລັກນ້ອຍ.

ຂອບເຂດຂະບວນການ ການປ່ຽນແປງ


ໃຫ້ສັງເກດວ່າໃນຂະນະທີ່ threads ຕົວເອງແມ່ນກະທູ້ປະຕິບັດແຍກຕ່າງຫາກແລະຂໍ້ມູນ Perl ແມ່ນ thread-
ເອກະຊົນເວັ້ນເສຍແຕ່ໄດ້ແບ່ງປັນຢ່າງຊັດເຈນ, ກະທູ້ສາມາດສົ່ງຜົນກະທົບຕໍ່ສະຖານະຂະບວນການ, ຜົນກະທົບຕໍ່
ກະທູ້ທັງໝົດ.

ຕົວຢ່າງທົ່ວໄປທີ່ສຸດຂອງນີ້ແມ່ນການປ່ຽນແປງໄດເລກະທໍລີທີ່ເຮັດວຽກໃນປະຈຸບັນໂດຍໃຊ້ "chdir()".
ກະທູ້ໜຶ່ງເອີ້ນວ່າ "chdir()", ແລະລະບົບການເຮັດວຽກຂອງກະທູ້ທັງໝົດປ່ຽນແປງ.

ຕົວຢ່າງທີ່ຮຸນແຮງກວ່າຂອງການປ່ຽນແປງຂອບເຂດຂະບວນການແມ່ນ "chroot()": ໄດເລກະທໍລີຮາກຂອງ.
ກະທູ້ທັງໝົດປ່ຽນແປງ, ແລະບໍ່ມີກະທູ້ໃດສາມາດຍົກເລີກມັນໄດ້ (ກົງກັນຂ້າມກັບ "chdir()").

ຕົວຢ່າງເພີ່ມເຕີມຂອງການປ່ຽນແປງຂອບເຂດຂະບວນການປະກອບມີ "umask()" ແລະການປ່ຽນແປງ uids ແລະ gids.

ຄິດວ່າການປະສົມ "ສ້ອມ()" ແລະກະທູ້? ກະລຸນານອນແລະລໍຖ້າຈົນກ່ວາຄວາມຮູ້ສຶກ
ຜ່ານ. ຈົ່ງຮູ້ວ່າຄວາມຫມາຍຂອງ "fork()" ແຕກຕ່າງກັນລະຫວ່າງເວທີ. ຍົກ​ຕົວ​ຢ່າງ,
ບາງລະບົບ Unix ຄັດລອກກະທູ້ໃນປະຈຸບັນທັງຫມົດເຂົ້າໄປໃນຂະບວນການຂອງເດັກນ້ອຍ, ໃນຂະນະທີ່ຄົນອື່ນພຽງແຕ່
ຄັດລອກກະທູ້ທີ່ເອີ້ນວ່າ "fork()". ເຈົ້າໄດ້ຖືກເຕືອນແລ້ວ!

ເຊັ່ນດຽວກັນ, ການປະສົມສັນຍານແລະກະທູ້ອາດຈະມີບັນຫາ. ການ​ປະ​ຕິ​ບັດ​ແມ່ນ​ເວ​ທີ -
ຂຶ້ນກັບ, ແລະແມ້ກະທັ້ງ POSIX semantics ອາດຈະບໍ່ເປັນສິ່ງທີ່ທ່ານຄາດຫວັງ (ແລະ Perl ບໍ່ໄດ້ເຖິງແມ່ນວ່າ
ໃຫ້ທ່ານ POSIX API ເຕັມ). ຕົວຢ່າງ, ບໍ່ມີວິທີທີ່ຈະຮັບປະກັນວ່າສັນຍານ
ຖືກສົ່ງໄປຫາຄໍາຮ້ອງສະຫມັກ Perl ຫຼາຍກະທູ້ຈະຖືກຂັດຂວາງໂດຍຫົວຂໍ້ໃດຫນຶ່ງ.
(ຢ່າງ​ໃດ​ກໍ​ຕາມ​, ຄຸນ​ນະ​ສົມ​ບັດ​ທີ່​ເພີ່ມ​ຂຶ້ນ​ບໍ່​ດົນ​ມາ​ນີ້​ສະ​ຫນອງ​ຄວາມ​ສາ​ມາດ​ທີ່​ຈະ​ສົ່ງ​ສັນ​ຍານ​ລະ​ຫວ່າງ​
ກະທູ້. ເບິ່ງ "ການເຊັນຊື່" ໃນຫົວຂໍ້ສໍາລັບລາຍລະອຽດເພີ່ມເຕີມ.)

ຄວາມປອດໄພກະທູ້ of ລະບົບ ຫ້ອງສະຫມຸດ


ບໍ່ວ່າຈະເປັນການໂທຫ້ອງສະໝຸດຕ່າງໆມີຄວາມປອດໄພກະທູ້ແມ່ນຢູ່ນອກການຄວບຄຸມຂອງ Perl. ໂທເລື້ອຍໆ
ທຸກທໍລະມານຈາກການບໍ່ປອດໄພກະທູ້ປະກອບມີ: "ເວລາທ້ອງຖິ່ນ()", "gmtime()", ຟັງຊັນ
ດຶງຂໍ້ມູນຜູ້ໃຊ້, ກຸ່ມ ແລະເຄືອຂ່າຍ (ເຊັ່ນ "getgrent()", "gethostent()",
"getnetent()" ແລະອື່ນໆ), "readdir()", "rand()", ແລະ "srand()". ໂດຍທົ່ວໄປ, ເອີ້ນວ່າ
ຂຶ້ນກັບບາງລັດພາຍນອກຂອງໂລກ.

ຖ້າລະບົບ Perl ຖືກລວບລວມຢູ່ໃນມີຕົວແປທີ່ປອດໄພຂອງສາຍຂອງການໂທດັ່ງກ່າວ, ພວກມັນຈະເປັນ
ໃຊ້. ນອກ​ຈາກ​ນັ້ນ​, Perl ແມ່ນ​ຢູ່​ໃນ​ຄວາມ​ເມດ​ຕາ​ຂອງ​ກະ​ທູ້​ຄວາມ​ປອດ​ໄພ​ຫຼື​ຄວາມ​ປອດ​ໄພ​ຂອງ​ການ​ໂທ​.
ກະ​ລຸ​ນາ​ປຶກ​ສາ​ຫາ​ລື​ເອ​ກະ​ສານ​ການ​ໂທ​ຫ້ອງ​ສະ​ຫມຸດ C ຂອງ​ທ່ານ​.

ໃນບາງແພລະຕະຟອມ, ການໂຕ້ຕອບຫ້ອງສະຫມຸດທີ່ປອດໄພກະທູ້ອາດຈະລົ້ມເຫລວຖ້າຫາກວ່າ buffer ຜົນໄດ້ຮັບແມ່ນເກີນໄປ
ຂະຫນາດນ້ອຍ (ຕົວຢ່າງ, ຖານຂໍ້ມູນກຸ່ມຜູ້ໃຊ້ອາດຈະໃຫຍ່ຫຼາຍ, ແລະ reentrant
ອິນເຕີເຟດອາດຈະຕ້ອງປະຕິບັດການຖ່າຍຮູບເຕັມຂອງຖານຂໍ້ມູນເຫຼົ່ານັ້ນ). Perl ຈະເລີ່ມຕົ້ນ
ກັບ buffer ຂະຫນາດນ້ອຍ, ແຕ່ສືບຕໍ່ retrying ແລະການຂະຫຍາຍຕົວ buffer ຜົນໄດ້ຮັບຈົນກ່ວາຜົນໄດ້ຮັບ
ເຫມາະ. ຖ້າຫາກວ່າການຂະຫຍາຍຕົວທີ່ບໍ່ມີຂອບເຂດຈໍາກັດນີ້ສຽງບໍ່ດີສໍາລັບຄວາມປອດໄພຫຼືການບໍລິໂພກຄວາມຊົງຈໍາເຫດຜົນທ່ານ
ສາມາດລວບລວມ Perl ຄືນໃໝ່ດ້ວຍ "PERL_REENTRANT_MAXSIZE" ທີ່ກຳນົດໄວ້ເປັນຈຳນວນສູງສຸດຂອງໄບຕ໌
ເຈົ້າຈະອະນຸຍາດໃຫ້.

ສະຫຼຸບ


ການສອນກະທູ້ທີ່ສົມບູນສາມາດຕື່ມຂໍ້ມູນໃສ່ປື້ມ (ແລະມີ, ຫຼາຍຄັ້ງ), ແຕ່ກັບສິ່ງທີ່ພວກເຮົາໄດ້
ກວມເອົາໃນການແນະນໍານີ້, ທ່ານຄວນດີຢູ່ໃນເສັ້ນທາງຂອງທ່ານທີ່ຈະກາຍເປັນ Perl threaded
ຊ່ຽວຊານ.

ໃຊ້ perlthrtut ອອນໄລນ໌ໂດຍໃຊ້ບໍລິການ onworks.net


ເຊີບເວີ ແລະສະຖານີເຮັດວຽກຟຣີ

ດາວໂຫຼດແອັບ Windows ແລະ Linux

  • 1
    Pascal Compiler ຟຣີ
    Pascal Compiler ຟຣີ
    A 32/64/16-bit Pascal compiler ສໍາລັບ
    Win32/64/CE, Linux, Mac OS X/iOS,
    Android, FreeBSD, OS/2, Game Boy
    Advance, Nintendo NDS ແລະ DOS;
    ເຂົ້າກັນໄດ້ wi...
    ດາວໂຫລດ Pascal Compiler ຟຣີ
  • 2
    ຂໍ້ມູນດິຈິຕອນ Canon EOS
    ຂໍ້ມູນດິຈິຕອນ Canon EOS
    Canon ບໍ່ມີການນັບ shutter
    ລວມຢູ່ໃນຂໍ້ມູນ EXIF ​​ຂອງ an
    ໄຟລ໌ຮູບພາບ, ກົງກັນຂ້າມກັບ Nikon ແລະ
    Pentax. ບໍ່ມີ Canon ຢ່າງເປັນທາງການ
    ຄໍາຮ້ອງສະຫມັກ ...
    ດາວໂຫລດຂໍ້ມູນ Canon EOS DIGITAL
  • 3
    rEFInd
    rEFInd
    rEFInd ແມ່ນທາງແຍກຂອງ rEFIt boot
    ຜູ້​ຈັດ​ການ. ເຊັ່ນດຽວກັນກັບ rEFIt, rEFInd ສາມາດເຮັດໄດ້
    ກວດ​ຫາ​ອັດ​ຕະ​ໂນ​ມັດ boot EFI ຂອງ​ທ່ານ​ຕິດ​ຕັ້ງ​
    loaders ແລະມັນນໍາສະເຫນີ GUI ງາມ
    ເມນູທາງເລືອກໃນການບູດ...
    ດາວໂຫລດ rEFInd
  • 4
    ExpressLuke GSI
    ExpressLuke GSI
    ຫນ້າດາວໂຫລດ SourceForge ນີ້ແມ່ນເພື່ອ
    ໃຫ້ຜູ້ໃຊ້ດາວໂຫລດແຫຼ່ງຂອງຂ້ອຍທີ່ສ້າງຂຶ້ນ
    GSIs, ອີງຕາມການທີ່ຍິ່ງໃຫຍ່ຂອງ phhusson
    ເຮັດວຽກ. ຂ້ອຍສ້າງທັງ Android Pie ແລະ
    Android 1...
    ດາວໂຫລດ ExpressLuke GSI
  • 5
    ນັກສະແດງດົນຕີ
    ນັກສະແດງດົນຕີ
    Music Caster ເປັນເຄື່ອງຫຼິ້ນດົນຕີຖາດ
    ທີ່​ເຮັດ​ໃຫ້​ທ່ານ​ຂັບ​ຮ້ອງ​ເພງ​ໃນ​ທ້ອງ​ຖິ່ນ​ຂອງ​ທ່ານ​ເປັນ​
    ອຸປະກອນ Google Cast. ໃນ​ການ​ແລ່ນ​ຄັ້ງ​ທໍາ​ອິດ​,
    ທ່ານ​ຈະ​ຕ້ອງ​ໄດ້​ຄລິກ​ໃສ່​ລູກ​ສອນ​ໃນ​ຂອງ​ທ່ານ​
    Tas...
    ດາວ​ໂຫຼດ​ເພງ Caster​
  • 6
    PyQt
    PyQt
    PyQt ແມ່ນການຜູກມັດ Python ສໍາລັບ
    Digia's Qt ຂ້າມເວທີ
    ໂຄງ​ຮ່າງ​ການ​ພັດ​ທະ​ນາ​ຄໍາ​ຮ້ອງ​ສະ​ຫມັກ​. ມັນ
    ຮອງຮັບ Python v2 ແລະ v3 ແລະ Qt v4 ແລະ
    Qt v5. PyQt ສາມາດໃຊ້ໄດ້...
    ດາວໂຫລດ PyQt
  • ເພີ່ມເຕີມ »

Linux ຄຳ ສັ່ງ

  • 1
    accs
    accs
    vadm - manipulate ແລະບໍລິຫານ
    ພື້ນຖານວັດຖຸສະບັບ ...
    ແລ່ນ accs
  • 2
    acdce
    acdce
    acdc - ທົດສອບໄຟລ໌ ACD ຂອງແອັບພລິເຄຊັນ ...
    ແລ່ນ acdce
  • 3
    coqchk.opt
    coqchk.opt
    coqchk - The Coq Proof Checker ລວບລວມ
    ກວດ​ສອບ​ຫ້ອງ​ສະ​ຫມຸດ ...
    ດໍາເນີນການ coqchk.opt
  • 4
    coqdep
    coqdep
    coqdep - ຄອມພິວເຕີ້ລະຫວ່າງໂມດູນ
    ການຂື້ນກັບໂຄງການ Coq ແລະ Caml ...
    ແລ່ນ coqdep
  • 5
    g-wrap-config
    g-wrap-config
    g-wrap-config - script ເພື່ອໃຫ້ໄດ້ຮັບ
    ຂໍ້ມູນກ່ຽວກັບສະບັບທີ່ຕິດຕັ້ງ
    ຂອງ G-Wrap ...
    ດໍາເນີນການ g-wrap-config
  • 6
    g.accessgrass
    g.accessgrass
    g.access - ຄວບຄຸມການເຂົ້າເຖິງ
    ແຜນ​ທີ່​ໃນ​ປະ​ຈຸ​ບັນ​ສໍາ​ລັບ​ຜູ້​ໃຊ້​ອື່ນໆ​ກ່ຽວ​ກັບ​ການ​
    ລະບົບ. ຖ້າບໍ່ມີທາງເລືອກໃຫ້, ພິມ
    ສະຖານະປັດຈຸບັນ. ຄໍາສໍາຄັນ: ທົ່ວໄປ, ແຜນທີ່
    ການ​ຄຸ້ມ​ຄອງ​, p ...
    ແລ່ນ g.accessgrass
  • ເພີ່ມເຕີມ »

Ad