Linguaggio di programmazione moderno con astrazioni di programmazione simultanee intuitive [closed]

39

Sono interessato all'apprendimento della programmazione concorrente, concentrandomi sull'applicazione / livello utente (non sulla programmazione di sistema). Sto cercando un linguaggio di programmazione moderno di alto livello che fornisca astrazioni intuitive per scrivere applicazioni concorrenti. Voglio concentrarmi sulle lingue che aumentano la produttività e nascondono la complessità della programmazione concorrente.

Per dare alcuni esempi, non considero una buona opzione scrivere il codice multithread in C, C ++ o Java perché IMHO la mia produttività è ridotta e il loro modello di programmazione non è intuitivo. D'altra parte, le lingue che aumentano la produttività e offrono astrazioni più intuitive come Python e il modulo multiprocessing, Erlang, Clojure, Scala, ecc., Sarebbero buone opzioni.

Che cosa consiglieresti in base alla tua esperienza e perché?

EDIT: Grazie a tutti per le vostre risposte interessanti. È difficile fare una conclusione senza tentare in realtà poiché ci sono molti buoni candidati: Erlang, Clojure, Scala, Groovy e forse Haskell. Ho votato la risposta con gli argomenti più convincenti, ma proverò tutti i buoni candidati prima di decidere quale scegliere:)

    
posta faif 12.03.2012 - 14:08
fonte

16 risposte

32

Quasi certamente dovresti dare un'occhiata a Clojure - secondo me è il miglior linguaggio moderno per la programmazione multi-core ed è estremamente produttivo.

Attributi chiave:

  • È un linguaggio funzionale , che è un vantaggio sia per la concorrenza che per la tua capacità di sviluppare utilizzando astrazioni di livello superiore. Presenta strutture dati permanenti e immutabili e sequenze pigre che saranno familiari a chiunque abbia esperienza in linguaggi funzionali come Haskell.
  • È dotato di un nuovissimo software di memoria transazionale per l'accesso simultaneo senza blocchi allo stato mutabile. Rendere sicuro il codice della concorrenza è spesso semplice come avvolgerlo in un blocco (dosync ....).
  • È un Lisp - che lo rende estremamente potente per la metaprogrammazione basata su macro e la generazione di codice. Ciò può portare vantaggi significativi produttività (saggio di Paul Graham - "Vincere le medie")
  • È un linguaggio JVM - quindi non solo hai accesso all'enorme varietà di librerie e strumenti nell'ecosistema Java, ma beneficia anche dell'enorme sforzo ingegneristico che ha contribuito alla realizzazione della JVM una piattaforma efficace per le applicazioni concorrenti sul lato server. Ai fini pratici, ciò gli conferisce un enorme vantaggio rispetto alle lingue che non hanno questo tipo di fondamento su cui basarsi.
  • È dinamico - il che si traduce in codice molto conciso e molta produttività. Si noti tuttavia che è possibile utilizzare i suggerimenti di tipo statico facoltativo per le prestazioni, se necessario.
  • La lingua è progettata attorno alle astrazioni che è alquanto difficile da spiegare, ma l'effetto netto è che ottieni una serie di caratteristiche relativamente ortogonali che puoi combinare per risolvere i tuoi problemi. Un esempio potrebbe essere l'astrazione della sequenza, che consente di scrivere codice che si occupa di ogni tipo di oggetto "sequenziale" (che include tutto da elenchi, stringhe, array Java, sequenze pigro infinite, righe da leggere da un file ecc.)
  • C'è una grande comunità - utile, perspicace ma soprattutto molto pragmatica: l'obiettivo di Clojure è generalmente quello di "fare le cose".

Alcuni esempi di mini codici con un limite di concorrenza:

;; define and launch a future to execute do-something in another thread
(def a (future (do-something)))

;; wait for the future to finish and print its return value
(println @a)

;; call two functions protected in a single STM transaction
(dosync
  (function-one)
  (function-two))

In particolare, vale la pena guardare uno o più di questi video:

risposta data 29.12.2014 - 14:36
fonte
27

Potresti provare D. Offre tre modelli. Raccomando il primo o il secondo.

  1. std.concurrency . Se si utilizza questo modulo per tutte le esigenze di concorrenza, una combinazione della lingua e della libreria standard impone l'isolamento tra i thread. I thread comunicano principalmente tramite il trasferimento di messaggi, con un supporto limitato per la memoria condivisa in un modo che favorisce "la sicurezza prima di tutto" e non consente la trasmissione di dati di basso livello. Sfortunatamente la documentazione di std.concurrency ha bisogno di miglioramenti, ma il modello è documentato in un capitolo gratuito del libro di Andrei Alexandrescu, "The D Programming Language".

  2. std.parallelism . Questo modulo è progettato specificamente per il parallelismo multicore piuttosto che la concorrenza del caso generale. ( Concurrency and parallelism non sono la stessa cosa, anche se la concorrenza è necessaria per attuare il parallelismo. ) Dato che l'intero punto del parallelismo è la performance, lo std.parallelismo non garantisce alcun isolamento perché renderebbe difficile la scrittura di codice parallelo efficiente. Tuttavia, astrae molti dettagli di basso livello soggetti a errori, quindi è molto difficile rovinare se stai parallelizzando i carichi di lavoro che hai verificato manualmente tra loro indipendenti.

  3. core.thread è un wrapper di basso livello su thread specifici del sistema operativo API. Sia std.concurrency che std.parallelism lo usano sotto il cofano, ma ti consiglio di usarlo solo se stai scrivendo la tua libreria di concorrenza o trovi qualche ridicolo caso d'angolo che non può essere fatto bene in std.parallelism o std .concorrenza. Nessuno dovrebbe usare qualcosa di basso livello per il lavoro quotidiano.

risposta data 03.06.2013 - 16:12
fonte
23

Erlang è sicuramente un'ottima opzione, ma qualcosa di un po 'più pratico potrebbe essere Vai , la nuova lingua di Google.

Non è così lontano dalle altre lingue comuni, quindi è generalmente facile da ottenere se conosci già altre lingue "facili". Molte persone lo confrontano con Python o addirittura con Lua in termini di come "comodo" è programmare.

    
risposta data 22.11.2011 - 19:56
fonte
23

Dai un'occhiata a Microsoft Parallel Programming for .net. È molto intuitivo.

Many personal computers and workstations have two or four cores (that is, CPUs) that enable multiple threads to be executed simultaneously. Computers in the near future are expected to have significantly more cores. To take advantage of the hardware of today and tomorrow, you can parallelize your code to distribute work across multiple processors. In the past, parallelization required low-level manipulation of threads and locks. Visual Studio 2010 and the .NET Framework 4 enhance support for parallel programming by providing a new runtime, new class library types, and new diagnostic tools. These features simplify parallel development so that you can write efficient, fine-grained, and scalable parallel code in a natural idiom without having to work directly with threads or the thread pool. The following illustration provides a high-level overview of the parallel programming architecture in the .NET Framework 4... http://i.msdn.microsoft.com/dynimg/IC292903.png

    
risposta data 03.06.2013 - 14:15
fonte
20

Sia Erlang che Scala hanno concorrenza basata sugli attori , che ho trovato molto intuitivo e facile da imparare.

The Actor model in computer science is a mathematical model of concurrent computation that treats "actors" as the universal primitives of concurrent digital computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received... It has been used both as a framework for a theoretical understanding of computation, and as the theoretical basis for several practical implementations of concurrent systems.

    
risposta data 03.06.2013 - 14:17
fonte
18

In questo momento sto imparando su Haskell e leggendo questo documento mi ha convinto che Haskell è una buona opzione per la programmazione concorrente. Poiché è puramente funzionale (il sistema di tipo sa se una funzione fa input, output o lettura / modifica dello stato globale), può fare cose come la memoria transazionale del software (sintetizzata molto bene nel documento sopra) che si comporta in modo simile alle transazioni nei database: ottieni un sacco di cose belle come l'atomicità con solo un po 'di zucchero in più. AFAIK, i fili Haskell sono anche molto leggeri. Oltre a queste cose, il fatto che Haskell sia puramente funzionale consente di eseguire anche semplici attività in parallelo con poco più di una sola parola chiave (par). fonte

    
risposta data 25.11.2011 - 09:26
fonte
7

La lingua GO di Google ha alcuni strumenti interessanti per la concorrenza - sarebbe un'altra cosa divertente da provare. Vedi: link e leggi un po 'per gli esempi.

Concurrent programming is a large topic and there is space only for some Go-specific highlights here.

Concurrent programming in many environments is made difficult by the subtleties required to implement correct access to shared variables. Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design. To encourage this way of thinking we have reduced it to a slogan:

Do not communicate by sharing memory; instead, share memory by communicating.

     

Questo approccio può essere preso troppo lontano. I conteggi di riferimento possono essere fatti meglio inserendo un mutex attorno a una variabile intera, per esempio. Ma come approccio di alto livello, l'uso dei canali per controllare l'accesso facilita la scrittura di programmi chiari e corretti.

     

Un modo per pensare a questo modello è considerare un tipico programma a thread singolo in esecuzione su una CPU. Non ha bisogno di primitive di sincronizzazione. Ora esegui un'altra istanza di questo tipo; anche questo non ha bisogno di sincronizzazione. Ora lascia che quei due comunichino; se la comunicazione è il sincronizzatore, non c'è ancora bisogno di altre sincronizzazioni. Le condotte Unix, ad esempio, si adattano perfettamente a questo modello. Sebbene l'approccio di Go alla concorrenza sia originato dai CSP (Communicating Sequential Processes) di Hoare, può anche essere visto come una generalizzazione sicura dei tipi di pipe Unix ...

    
risposta data 03.06.2013 - 14:19
fonte
6

Consiglierei comunque C ++. È più che capace delle necessarie astrazioni per scrivere un codice concorrente decente. La schiacciante probabilità è che si abbia semplicemente una libreria scadente per fare il lavoro, dal momento che le buone librerie per fare il lavoro sono relativamente nuove, e infatti, la conoscenza per usare bene C ++ non è esattamente comune. La TBB di Intel è in circolazione solo da alcuni anni e la PPL di Microsoft è stata spedita solo dallo scorso anno.

Se usi qualcosa come TBB o PPL, allora il codice concorrente è, beh, non esattamente banale da scrivere, nella misura in cui la concorrenza non è mai banale, ma lungi dall'essere ardua. Se usi direttamente pthreads o thread Win32, non c'è da stupirsi che non ti piaccia- praticamente stai scrivendo in assembler con tali funzioni. Ma con la PPL, allora stai parlando di algoritmi funzionali standard che sono per te paralleli, strutture dati generiche per accesso concorrente e quel tipo di cose buone.

    
risposta data 23.11.2011 - 09:05
fonte
6

Qui è necessaria una presa per Ada , in quanto contiene tutte le astrazioni di livello superiore per il parallelismo e l'amp; concorrenza. altrimenti noto come incarico . Anche come OP chiesto intuitivo (un criterio soggettivo!) Penso che un approccio diverso al mondo java-centrico possa essere apprezzato.

    
risposta data 25.11.2011 - 11:21
fonte
5

Nella prossima versione, C # lo rende ancora più semplice di quanto mostra il diagramma. Ci sono due nuove parole chiave Async e Attendi.

Async viene usato come modificatore di funzione e dice "questa operazione esegue il suo lavoro su un altro thread.

Attendere è usato all'interno di una funzione Asincrona, ed è qui che avviene la magia. Fondamentalmente Attendi al compilatore di eseguire l'operazione seguendo la parola chiave in un thread separato e attendere i risultati. Qualsiasi codice dopo la chiamata di attesa viene eseguito dopo l'operazione.

ANCHE, l'operazione si sincronizza con il thread chiamante (quindi se stai facendo un'operazione asincrona in risposta a un clic di un pulsante, non è necessario postare manualmente il thread dell'interfaccia utente). Due piccole parole chiave e ottieni un sacco di potere della concorrenza. Per saperne di più here

    
risposta data 22.11.2011 - 20:39
fonte
5

Suggerirei Groovy / Java / GPars se puoi essere basato su JVM poiché consente attori, flusso di dati, processi sequenziali comunicanti (CSP), parallelismo dei dati, memoria transazionale del software (STM), agenti, ... Il punto qui è che ci sono molti concorrenti di alto livello e modelli di parallelismo ognuno dei quali ha diversi "punti dolci". Non si desidera utilizzare un modello non in armonia con la soluzione di un problema che si sta tentando di costruire. Le lingue e i framework con un solo modello ti costringono all'algoritmo di hacking.

Naturalmente potrei essere considerato di parte perché contribuisco a Groovy e GPars. D'altra parte lavoro con CSP e Python, cf. Python-CSP.

Un altro punto è che la domanda iniziale riguarda l'apprendimento, non la scrittura di un sistema di produzione. Quindi la combinazione di Groovy / Java / GPars è un buon modo di apprendimento anche se l'eventuale lavoro di produzione viene eseguito in C ++ usando qualcosa come Just :: Thread Pro o TBB piuttosto che basato su JVM.

(Alcuni collegamenti URL perfettamente ragionevoli dovevano essere rimossi a causa di un panico riguardo allo spamming da parte del sito host.)

    
risposta data 23.11.2011 - 18:18
fonte
4

Che mi dici di Clojure? Ad esempio, è possibile utilizzare Swing ma è possibile usufruire della funzione di programmazione simultanea Clojure? Clojure ha un'integrazione Java molto buona.

Inoltre, hai preso in considerazione Java 7 Fork / Join framework ?

    
risposta data 22.11.2011 - 22:31
fonte
2

Potresti anche consultare Groovy e GPars libreria. GPars BTW è in qualche modo simile a .NET Parallel Extension menzionato in un'altra risposta, ma la sintassi flessibile di Groovys lo fa leggere meglio in alcune circostanze.

    
risposta data 22.11.2011 - 20:53
fonte
0

Scala è stato menzionato più volte nelle domande e nelle risposte, ma non ho visto alcun riferimento a Akka che è un'implementazione dell'attore che può essere usato sia con Scala sia con Java.

    
risposta data 21.04.2012 - 23:51
fonte
-1

Penso che dipenda da cosa stai costruendo. App desktop o server? Ho sentito che (ma non ho esperienza personale) node.js è ottimo per la programmazione simultanea per server (sia in termini di scrittura di codice che di prestazioni). Se volessi scrivere una nuova app server, probabilmente la proverei. Non sono sicuro delle app desktop ... Ho scritto un bel po 'di roba in C # e ci sono alcuni strumenti che nascondono la complessità piacevolmente, anche se per altri casi devi affrontarlo a testa alta.

    
risposta data 22.11.2011 - 19:42
fonte
-1

Potrei essere colpito in testa per questo, ma hai letto capitolo 7 di TAOUP ? La sezione a cui sto pensando specificamente è thread vs processes. Ho scoperto che il concetto di elaborazione simultanea fa sì che la maggior parte delle persone pensi ai thread, eppure non ho mai visto un'istanza in cui un thread sia più facile e veloce da utilizzare rispetto alla generazione di un processo figlio.

Stai coltivando tutti i dettagli della gestione della concorrenza ai ragazzi intelligenti che hanno creato il tuo sistema operativo. Esistono già molti metodi di comunicazione e non devi preoccuparti del blocco delle risorse condivise. Fondamentalmente, i thread sono un hack di efficienza, che rientra nella regola dell'ottimizzazione. Non ottimizzare se non hai provato per necessità.

Trova una buona libreria di sottoprocesso, come envoy per python . O potresti semplicemente scrivere diversi programmi separati in C e scrivere un altro programma "master" per usare fork e pipe per generare e comunicare con i sottoprocessi.

    
risposta data 12.03.2012 - 15:07
fonte

Leggi altre domande sui tag