Intueamur quomodo concurrentes et paralleli opera programmandi in .Net, philosophorum prandiorum exemplo utentes. Consilium hoc est, a sequela/processus synchronisation ad exemplar actoris (in partibus sequentibus). Articulus potest esse utilis ad primam noticiam vel ad tuam scientiam reficiendam.
Cur etiam hoc facere norunt? Transistores suam minimam magnitudinem attingunt, lex Moore terminum celeritatis lucis ferit, et ideo incrementum in numeris observatur: plures transistores fieri possunt. Eodem tempore, summa notitiarum incrementa, et utentes exspectant responsum a rationibus immediatum. In tali condicione programmatis "normalis", cum unum filum exsequens habemus, iam non est efficax. Non opus est aliquo modo quaestionem solvere de executione simultanei vel concurrentis. Quaestio autem haec in diversis gradibus existit: in gradu sequelae, in gradu processus, in machinis in retis (ratio distributa). . NET summus qualitas, technologiae probatae pro cito et efficaciter solvendas huiusmodi difficultates habet.
negotium
Edsger Dijkstra quaestionem discipulis suis anno 1965 retraxit. Statuta formula talis est. Sunt quidam philosophorum numero totidemque tridentes. Sedent ad mensam rotundam, inter eas tridentes. Philosophi de laminis infinitis cibis vesci possunt, cogitare vel expectare. Comedere debet philosophus duas furcas, haec furcam cum illa communicat. Electio et impositio furca sunt duae actiones separatae. Omnes philosophi tacent. Negotium est talem algorithmum invenire ut omnes cogitent et etiam post 54 annos bene alantur.
Primum, conemur hanc quaestionem solvere utendo spatio communi. Fuscinulae in communi mensa iacent, et philosophi simpliciter sumunt eas, cum ibi sunt, et eas reponunt. Unde haec problemata synchronisationi oriuntur, quando exacte ad tridentes capiuntur? quid faciam si non est obturaculum? etc. Sed primum a philosophis ordiamur.
Ad fila incipere filo utimur per piscinam Task.Run modum;
var cancelTokenSource = new CancellationTokenSource();
Action<int> create = (i) => RunPhilosopher(i, cancelTokenSource.Token);
for (int i = 0; i < philosophersAmount; i++)
{
int icopy = i;
// ΠΠΎΠΌΠ΅ΡΡΠΈΡΡ Π·Π°Π΄Π°ΡΡ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ ΠΏΡΠ»Π° ΠΏΠΎΡΠΎΠΊΠΎΠ². ΠΠ΅ΡΠΎΠ΄ RunDeadlock Π½Π΅ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡΡ
// ΡΡΠ°Π·Ρ, Π° ΠΆΠ΄Π΅Ρ ΡΠ²ΠΎΠ΅Π³ΠΎ ΠΏΠΎΡΠΎΠΊΠ°. ΠΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠΉ Π·Π°ΠΏΡΡΠΊ.
philosophers[i] = Task.Run(() => create(icopy), cancelTokenSource.Token);
}
Stagnum sequela ad optimize creationem et remotionem staminum destinatur. Haec piscina quenam officiorum habet et CLR fila gignit vel delet secundum numerum horum operum. Una piscina omnibus AppDomains. Id lacus sit amet semper fere, nam... non opus est molestare cum fila creando et delendo, earum queues, etc. Facere potes sine piscina, sed tunc habebis ea directe. Thread, hoc utile est in casibus, cum filo prioritatem mutare necesse est, cum longam habemus operationem, pro filo fabricatorio, etc.
In aliis verbis, System.Threading.Tasks.Task genus idem Threadsed cum omni commodorum commodo: facultas inferendi negotium post stipitem aliorum munerum, eas a muneribus, et multo magis commode interpellet. etc. Opus sunt ad constructiones async/exspectandas (Asynchronum Negotium fundatum Exemplum, saccharum syntacticum ad operationes IO exspectandas). De hoc postea dicemus.
CancelationTokenSource hic necesse est ut signum e filo se terminet.
Hic primum tentamus sumendo laevam, deinde furcam dextram, et si operatur, comedimus et reducimus; Furca sumens est atomica, i.e. duo stamina non possunt unum simul capere (iniuria: prima legit furca liberam, secunda eadem facit, prima capit, altera sumit). Quia haec Interlocked.CompareExchange, quae instrui debet per processum instructionem .TSL, XCHG) , quod particulam memoriae pro atomicis sequentiae lectionis et scribendi genere comprimit. Et SpinWait valet ad constructionem while(true) solum cum paulo "magicae" - stamina processus tollit (Thread.SpinWaitsed interdum in aliud linum imperium transit ( . )Thread.Yeild) Vel obdormivit (Thread.Sleep).
Sed haec solutio non operatur, quia. stamina mox (intra secunda mihi) praeclusa sunt: ββlaeva furca philosophi omnes capiunt, sed non est rectum. Fuscinulae deinde ordinatae sunt valores: 1 2 3 4 5 .
In tabula interclusio staminum (deadlock). Viridis supplicium indicat, rubra synchronisationem indicat, et griseum filum indicat dormientem. Crystallini designant Lorem tempus Tasks.
Fames Philosophorum
Quamvis non multum cibi ad cogitandum opus sit, fames aliquem philosophiam dare potest. Studeamus in problemate nostro famem sequelae condicionem simulare. Fames est cum filum operatur, sed sine opere significanti aliis verbis idem est lock, nunc tantum filum non dormit, sed active quaerit aliquid edendi, sed cibus non est. Ad frequentes interclusiones vitandas, reducemus bifurcam, si alteram capere non potuimus.
Gravis est in hoc codice duo philosophorum quattuor philosophorum laevam furcam ponere. Et evenit ut plus comedant cibum, et alii incipiant esurire, licet stamina tantundem habeant prioritatem. Hic non sunt ieiunantes, quia... mali philosophi interdum tridentes reponunt. Evenit ut boni minus quam mali 5 edant. Ita parvus error in codice effectus guttam ducit. Hic etiam notandum est, quod rarum situm esse potest, cum omnes philosophi levant sinistrum, non est dextrum unum, ponunt sinistrum unum, expecta, sume sinistrum iterum, etc. Haec condicio est etiam famis, venenatis mutui similior. Non potui repetere. Subter pictura est in qua duo mali philosophi utrumque tridentem sumpserunt, et duo boni ieiunaverunt.
Hic videre potes quod stamina interdum excitare et opum acquirere conantur. Duo ex quattuor coros nihil faciunt (graphi viridis supra).
Mors Philosophi
Illud magis dubium, quod gloriosum philosophorum convivium interpellare potuit, si unus ex illis in manibus furcis subito moritur (et sic sepelietur). Tum vicini sine prandio relinquentur. Potes adire cum exempli causa in hoc ipso casu, exempli gratia, abjectus est NullReferenceException postquam philosophus sumit tridentes. Et obiter, exceptio non tractabitur, et vocatio codicem non simpliciter capiet (hoc enim AppDomain.CurrentDomain.UnhandledException et etc.). Ergo erroris tracto opus est in ipsis filis et cum lepide terminatione.
Famulus potionem
Bene, quomodo solvemus hanc quaestionem de mortibus, inedia, et mortibus? Unum tantum philosophum patiemur ad tridentes, et exclusionem staminum huic loco addamus. Quomodo facere? Finge proximum philosophos esse ministratorem qui permittit uni philosopho tridentem sumere. Quomodo hunc architriclinum facere debeamus et quomodo philosophi ab eo petant quaestiones sunt iucundae.
Simplicissima via est philosophorum ut simpliciter constanter peteret architriclinus aditum ad tridentes. Illae. Nunc philosophi non exspectant furcam prope, sed expecta vel rogant architriclinus. Primo tantum Spatium User ad hoc utimur, in eo non obloquiis utimur aliquem processum a nucleo vocare (plura de his infra).
User spatium solutiones
Hoc idem faciemus, quod ante fecimus cum una furca et duobus philosophis, nos in ansa trahere et expectare. Nunc vero omnes philosophi et quasi furca una, i.e. solum philosophum possumus dicere, qui hoc "furca aurea" ab architriclino sumpsit. Ad hoc utimur SpinLock.
SpinLock hoc obstructus est, cum fere loquendo idem while(true) { if (!lock) break; }sed magis magia quam in SpinWait (quae ibi). Nunc novit computare expectantes, paululum et plus dormire. etc. In genere omnia facit ad optimize possibilia. Sed tenendum est hanc adhuc eandem esse ansam activam quae processus facultates exedens et filum tenet, quod ad famem ducere potest si unus philosophorum prior fit quam ceteri, sed furcam auream non habet. ). Propterea utimur eo modo ad brevissimas mutationes communium memoriarum, sine ulla tertia-pars appellatio, comae nestae, vel aliae admirationis.
drawing for SpinLock. Rivi constanter "pugnant" pro furca aurea. Defectus occurrunt - area clara in figura. Cores plene non utuntur: ab his stamina circiter 2/3 quatuor tantum.
Alia solutio hic erit ad solum usum Interlocked.CompareExchange cum eadem activa exspectatione, ut in codice supra (in philosophorum fame pereo), hoc autem, ut iam dixi, obsisteret theoretice posset.
in Interlocked valet dicere quod non solum CompareExchangesed etiam alii methodi legendi atomi ET scribendi. Et iterando mutationem, si alius stamina efficit ut suas mutationes faciat (legere 1, lege 2, scribe 2, scribe 1 malum est), potest adhiberi ad varias mutationes ad unum valorem (Interlocked Quidquid exemplaris).
Kernel modus solutionum
Ut facultates absumptis in ansa, inspiciamus quomodo filo intercluderetur. Id est, exemplo nostro continuato, videamus quomodo philosophum architriclinus dormiat et evigilet, nisi cum necesse fuerit. Primum videamus quomodo hoc facere per modum nuclei operandi ratio. Omnes structurae ibi saepe desinunt tardiores esse quam in spatio usoris. Saepius tardius, e.g AutoResetEvent maybe LIII temporibus tardius SpinLock [Richter]. Sed cum eorum auxilio, processus per totam rationem synchronize potes, vel non administrari.
Praecipuum consilium hic semaphorum est, quod ante Dijkstra plus quam dimidium saeculum proponitur. Semaphora simpliciter ponitur, integer affirmativus systematis regitur et duae operationes in eo - augmentum et diminutio. Si nulla res minui non potest, vocationis linum impeditur. Cum numerus alio activo filo/processui augetur, tum stamina transeunt et semaphorum numerus transmissus iterum minuitur. Impedimenta in ampulla cum semaphore fingere potes. .NET plura construit cum similibus functionality: AutoResetEvent, ManualResetEvent, Mutex ipsum Semaphore. Nos utemur AutoResetEventhaec constructio simplicissima est: duo tantum valores 0 et 1 (falsus, verus). Methodus eius WaitOne() stamina dictamen impedit, si valor 0 erat, et si 1, eum ad 0 deponit et saltat. Methodus Set() crescit ad 1 and lets one person through, who again decrescat 0. Acts like turnstile in the subway.
Inpediamus solutionem et interclusionem pro unoquoque philosopho utamur, et non semel. Illae. Sed plures philosophi simul possunt manducare, et non unum. Sed rursus aditum ad mensam impedimus ut tridentes recte capiamus, condiciones generis vitantes.
Ad intelligendum quid hic aguntur, considera quando philosophus neglexerit tridentem, actiones eius sic erunt. Aditus ad mensam exspectat. Accepto tridente conatur. Non elaborare. Dat aditum ad mensam (mutua exclusio). Et transit suum "turturem" (AutoResetEvent) (primo patent). iterum in cyclum cadit, quia Non habet fuscinulas. Eas capere conatur et ad suum "turstile" sistit. Aliquis felicior vicinus dextra laevaque edens, philosophum nostrum aperiendo turturem. Noster philosophus secundo percurrit. Tertium tridentem sumere conatur. Prosperum. Atque it per turntilem prandere.
Cum in tali codice temere errores insunt (qui semper exstant), exempli gratia vicinus perperam specificetur vel idem obiectum creabitur. AutoResetEvent omnibus (Enumerable.Repeat) philosophi tincidunt exspectabunt, quia Errores in tali codice invenire admodum difficile est. Alia quaestio huius solutionis est quod non praestat aliquem philosophum non esurire.
Hybrid solutiones
Duos aditus synchronisationi inspeximus, cum in usuario modo manemus et in ansa subtegimus et cum filum per nucleum intercludimus. Primus modus prodest brevibus caudices, secundus longis. Saepe debes primum breviter exspectare variationem mutandi in ansa, et deinde stamina obstrue cum longa mora est. Aditus ad effectum sic dictum. hybrid designs. Eadem constructio quae in nucleo modo habet, nunc cum ansa utentis; SemaphorSlim, ManualResetEventSlim Maxime populare consilium hic est etc Monitor, quod in C # ibi notus lock syntaxis. Monitor hoc idem semaphore cum maximo valore 1 (mutex), sed cum auxilio exspectationis in ansa, recursione, conditione variabili exemplari (more infra) etc. Inspiciamus solutionem cum ea.
Hic rursus totam mensam impedimus ne ad uncinos accessus, nunc omnia fila statim absolvimus, quam vicini cum quis edendi finit. Illae. Uno modo, quis proximos manducat et impedit, et cum hoc aliquis finit, sed statim vult iterum comedere, vadit in scandalum et evigilat proximos suos, quia. morae tempus minus est.
Sic mortifera et inedia alicuius philosophi vitamus. Ansa utimur ad breve tempus exspectandum et filum diu obstruunt. Expeditio omnis statim tardior est quam si modo proximus erat apertus, ut in solutione AutoResetEventsed differentia non debet esse magna, quia relatorum debet in user modus primus.
Π£ lock syntaxin habet aliquid ingratum elit. Commendatur ut Monitor directe [Richter] [Eric Lippert]. Unus eorum est lock semper exeat Monitoretiam si exceptio facta est, et tunc aliud filum potest mutare statum comunis memoriae. His in casibus, saepe melius est in mortificatione vel in aliquo progressione tuto terminari. Aliud mirum est quod Monitor horologium utitur caudices (SyncBlock) quae sunt in omnibus obiectis. Si ergo objectum indebitum deligatur, facile potes deadlock (exempli gratia, si filo interposita claudas). Ad hoc occultum semper utimur.
Conditio Variabilis exemplaris permittit ut brevius efficiatur exspectatio alicuius condicionis implicatae. In .NET imperfecta est, opinor, quia... In theoria, plures esse debent queues in pluribus variabilibus (ut in Threads Posix), non in uno lock. Posset etiam facere omnes philosophos. Sed etiam in hac forma codicem tibi permittit breviare.
Multi philosophorum or async / await
Bene, nunc efficaciter fila impedire possumus. Sed quid, si multum philosophorum habemus? 100? 10000? Exempli gratia: 100000 petitiones interretiali servo recepimus. Pro singulis stamina creandis carus erit, quia tot stamina non erunt in parallela facienda. Tantummodo totidem nuclei logici exsecutioni mandabuntur (I have 4). Et omnes alii facultates simpliciter auferent. Una solutionis huius problematis est async / exspectatio exemplaris. Idea est quod munus non tenet linum si opus est exspectare aliquid pergere. Et cum aliquid fit, supplicium repetit (non autem necessario in eodem filo). In casu nostro fuscinulam exspectabimus.
SemaphoreSlim habet hoc WaitAsync() modum. Hic est exsecutio exemplaris usus.
Modus cum async / await in machinam finitam versutam translatum est, quae statim reddit internum suum Task. Per eam, potes expectare modum complendi, destruendi, et omnia alia quae facere cum Negotium potes. Intra modum, machina publica exsecutionem moderatur. In ima linea est, ut si nulla mora sit, supplicium synchronum est, et, si est, tum stamen solutum est. Ad meliorem huius intelligentiam, melius est intueri hanc rem publicam. Vincula ex his potes creare async / await modis.
Experiamur. Opus 100 philosophorum super machinam cum 4 zoologicis logicis, 8 secundis. Praevia solutio cum Monitor primas 4 stamina tantum perfecit et reliquas omnino non exercuit. Uterque horum 4 stamina ociosus erat circiter 2ms. Et async / exspectatio solutionis omnes 100 fecit, cum mediocris 6.8 secundis singulis exspectantibus. Utique in realibus systematibus, otiosis pro 6 secundis, inconveniens est et melius est non tot petitiones hoc modo procedere. Solutio cum Monitor evasit omnino non scalabilem esse.
conclusio,
Ut ex his parvis exemplis videre potes, .NET subsidia multa constructio synchronisationi. Sed non semper patet quomodo utatur. Spero hunc articulum utile fuisse. Hoc nunc involvimus, sed adhuc multum superest supellectilem interesting, exempli gratia, collectiones fila tuta, TPL Dataflow, programmatio reactiva, exemplar Transactionis Software, etc.