views:

517

answers:

11

I was reading how Clojure is 'cool' because of its syntax + it runs on the JVM so it is multithreaded etc. etc.

Are languages like ruby and python single threaded in nature then? (when running as a web app).

What are the underlying differences between python/ruby and say java running on tomcat?

Doesn't the web server have a pool of threads to work with in all cases?

+3  A: 

Certainly the webserver will have a pool of threads. That's only outside the control of your program. Those threads are used to handle HTTP requests. Each HTTP request is handled in a separate thread and the thread is released back to pool when the associated HTTP response is finished. If the webserver doesn't have such a pool, it would have been extremely slow in serving.

Whether a programming language is singlethreaded or multithreaded dependens on the possibility to programmatically spawn new threads using the language in question. If that isn't possible, then the language is singlethreaded, for example PHP. As far as I can see, both Ruby and Python supports multithreading.

BalusC
As a related/more specific question: Would a person new to Ruby/Rails need to do anything fancy when deploying a web app or CGI script to get that webserver pool functionality? i.e. if I were to just copy my .rb files to a webserver, would the webserver be able serve multiple concurrent requests using the same code, or is there some fancy config needed?
LoveMeSomeCode
Well, there's generally a bit more to deploying a Ruby app than just copying files over and pointing the webserver at them, but yes, the server handles spawning new threads (or processes) by itself.
Xiong Chiamiov
+4  A: 

Most languages don't define single or multithreading. Usually, that is left up to the libraries to implement.

That being said, some languages are better at it than others. CPython, for instance, has issues with interpreter locking during multithreading, Jython (python running on the JVM) does not.

Some of the real power of Clojure (IMO) is that it runs on the JVM. You get multithreading and tons of libraries for free.

ablerman
why closure over java? its short syntax?
Blankman
@Blankman - why *any* language over any other? There are many, **many** reasons why one may choose Clojure over Java or vice versa; suffice to say, a one-liner response in a comment would be insufficient to address the question. ablerman's point was simply that Clojure can piggyback on one of Java's major advantages as well as offering its own.
Andrzej Doyle
+1 to Andrzej comment. Also I would say that for me the Syntax is what drew me to Clojure away from Python and C#. And this coming from a guy who finds Java appalling. To each his own.
Timothy Baldridge
A: 

Ruby

The Ruby Interpreter is single threaded, which is to say that several of its methods are not thread safe.

In the Rails world, this single-thread has mostly been pushed to the server. So, you'll see nginx running with a pool of mongrel servers, each of which has an interpreter in memory, processes 1 request at a time, and in its own thread.

Passenger, running "ruby enterprise" brings the concept of garbage collection and some thread safety into Rails, and it's nice.

Still work to be done in Rails on this area, but it's getting there slowly -- but in general, the idea is to have multiple services and servers.

Jesse Wolgamott
"The Ruby Interpreter is single threaded": Wrong. First of all, there is no such thing as "the Ruby Interpreter". There is about a dozen or so of those, and all but one of them are multi-threaded. "Passenger, running Ruby Enterprise Edition brings the concept of garbage collection": Wrong. *All* Ruby Implementations have garbage collection and have *always* had garbage collection ever since the very first version 17 years ago. Also, REE has nothing to do with thread-safety. And it doesn't "bring anything into Rails", in fact, it has nothing to do with Rails, it's just a Ruby implementation ...
Jörg W Mittag
... like any other. (In fact, it's not even really even a Ruby implementation, it's just a small set of patches to MRI.)
Jörg W Mittag
You're right about the garbage collection, poor choice of words; I meant that it allows connections and other memory objects to be reused across 'passengers', resulting in a lower memory footprint and a higher concurrency count. YMMV, but in my experience, it's a good thing.
Jesse Wolgamott
A: 

How to untangle the knots in al those threads...

Clojure did not invent threading, however it has particularly strong support for it with Software Transactional Memory, Atoms, Agents, parallel map operations, ...

All other have accumulated threading support. Ruby is a special case as it has green threads in some implementations which are a kind of software emulated threads and do not use all the cores. 1.9 will put this to rest.

Regarding web servers, no they do not always work multithreaded, apache has traditionally ran as a flock of daemons which are a pool of separate single threaded processes. Now currently there are more options to run apache servers.

To summarize all modern languages support threading in one form or another.

The newer languages like scala and clojure are adding specific support to improve working with multiple threads without explicit locking as this has traditionally be the great pitfall of multithreading.

Peter Tillemans
+6  A: 

Both Python and Ruby have full support for multi-threading. There are some implementations (e.g. CPython, MRI, YARV) which cannot actually run threads in parallel, but that's a limitation of those specific implementations, not the language. This is similar to Java, where there are also some implementations which cannot run threads in parallel, but that doesn't mean that Java is single-threaded.

Note that in both cases there are lots of implementations which can run threads in parallel: PyPy, IronPython, Jython, IronRuby and JRuby are only few of the examples.

The main difference between Clojure on the one side and Python, Ruby, Java, C#, C++, C, PHP and pretty much every other mainstream and not-so-mainstream language on the other side is that Clojure has a sane concurrency model. All the other languages use threads, which we have known to be a bad concurrency model for at least 40 years. Clojure OTOH has a sane update model which allows it to not only present one but actually multiple sane concurrency models to the programmer: atomic updates, software transactional memory, asynchronous agents, concurrency-aware thread-local global variables, futures, promises, dataflow concurrency and in the future possibly even more.

Jörg W Mittag
+1 So, are the *"default"* implementations of Python and Ruby ( you know those where Guido and Matz participate ) *single threaded*?
OscarRyz
I cannot speak for Python, but as for Ruby, there is no such thing as a "default implementation". There is a Language Specification and there is a bunch of compilers and/or interpreters that implement that Language Specification. Every compiler or interpreter that faithfully implements the specification is a Ruby implementation and none of those is in some way special or "default" or whatever.
Jörg W Mittag
Technically the stock implementations "are multi-threaded". But because of the Global Interpreter Lock only one thread can execute at a time. So in essence...no they are not multi-threaded. This applies to both Ruby and Python.
Timothy Baldridge
@Jorg....let's say I go to www.ruby-lang.org and hit "download"....that's what the OP and I think most people would consider the "default implementation".
Timothy Baldridge
@Jorg, he defined the default ruby to be "the one Matz works on", which i think is a pretty fair default.
Peter Recore
It's a bit of an overstatement to say CPython cannot run threads in parallel - the threads run concurrently but cannot make use of multiple processors except in defined locations (like waiting for I/O on a file or socket, or when using some C libraries, for instance lxml allows parallel execution when parsing). The performance penalty on multiple processors only affects a small number of situations.
Ian Bicking
Ruby version 1.8 has two main implementations: MRI and JRuby. And as far 1.9 goes, YARV is the most common. So definetly you could say that MRI/YARV are the defaults. And by definition of default the most popular and widespread implementations are considered. And thats probably pretty clear to anyone working with ruby so i see no reason to pick over wording. Just my 2 cents.
Tanel Suurhans
To paraphrase the lawyer joke, the implementation of ruby used by 95% of users (YARV/MRI) gives the language a bad name!
Andrew Grimm
+1  A: 

The short answer is yes, they are single threaded.

The long answer is it depends.

JRuby is multithreaded and can be run in tomcat like other java code. MRI (default ruby) and Python both have a GIL (Global Interpreter Lock) and are thus single threaded.

The way it works for web servers is further complicated by the number of available server configurations. For most ruby applications there are (at least) two levels of servers, a proxy/static file server like nginx and then the ruby app server.

Nginx does not use threads like apache or tomcat, it uses non-blocking events (and I think forked worker processes). This allows it to deal with higher levels of concurrency than would be allowed with the overhead and scheduling inefficiencies of native threads.

The various ruby apps servers also work in different ways to get high throughput and concurrency without threads. Thin uses libev and the asynchronous evented model like Nginx. Mongrel uses a round-robin pool of worker processes. Unicorn uses native Unix IPC (select on a socket) to load balance to a pool of forked processes through one master proxy socket.

Threads are only one way to address concurrency. Multiple processes and evented models are a different approach that ties in well with the Unix base. This is fundamentally different from the way Java treats the world.

Ben Hughes
short answer is wrong, Python is multi-threaded, it is just that the C implementation does not allow true concurrency of the threads, but it is still multi-threaded.
fuzzy lollipop
when does the global interpreter lock kick in the prevent a true multi-threaded enviro?
Blankman
The GIL protects a Python thread from entering the bytecode interpeter if there already is one. This means that *only* running inside the interpreter is protected. For example, multiple Python threads running C code from C extensions is perfectly fine. Also, multiple C threads running is also fine. The only thing that doesn't work is multiple *Python* threads running *Python* code. (Of course, C extensions themselves may have *their own* locks. And obviously, if a C thread from an extension wants to enter the interpreter on behalf of a Python thread, then *it* needs to get the GIL as well.)
Jörg W Mittag
+3  A: 

CPython has a Global Interpreter Lock which can reduce the performance of multi-threaded code in Python. The net effect, in some cases, is that threads can't actually run simultaneously because of locking contention. Not all Python implementations use a GIL so this may not apply to JPython, IronPython or other implementations.

The language itself does support threading and other asynchronous operations. The python libraries can also support threading internally without exposing it directly to the Python interpreter.

If you've heard anything negative about Python and threading (or that it doesn't support it), it is probably someone encountering a situation where the GIL is causing a bottleneck..

James Schek
+2  A: 

A few interpreted programming languages such as CPython and Ruby support threading, but have a limitation that is known as a Global Interpreter Lock (GIL). The GIL is a mutual exclusion lock held by the interpreter that prevents the interpreter from concurrently interpreting the applications code on two or more threads at the same time, which effectively limits the concurrency on multiple core systems.

from wikipedia Thread

tkr
First of all, there is no such thing as an "interpreted programming language". Interpretation is a trait of the implementation, not the language; *any* language can be implemented by either a compiler or an interpreter, most are implemented by both. Secondly, CPython is not programming language, it's programming language *implementation*. Thirdly, it's not even an interpreter, CPython is a *compiler*. Fourth, neither Python nor Ruby have a GIL. *One* Python implementation and *two* (out of a dozen) Ruby implementations have a GIL, but again, a GIL is not a trait of the language not the impl.
Jörg W Mittag
A: 

Reading these answers here... A lot of them try to sound smarter than they really are imho (im mostly talking about Ruby related stuff as thats the one i'm most familiar with). In fact, JRuby is currently the only Ruby implementation that supports true concurrency. On JVM Ruby threads are mapped to OS native threads, without GIL interfering. So its totally correct to say that Ruby is not multithreaded. In 1.8.x Ruby is actually run inside one OS thread, and while you do have the fake feeling of concurrency with green threads, then in reality GIL will pretty much prevent you from having true concurrency. In Ruby 1.9 this changed a bit, as now a Ruby process can have many OS threads attached to it (plus the green threads), but again GIL will totally destroy the point and become the bottleneck.

In practice, from a regular webapp standpoint, it should not matter much if its single or multithreaded. The problem mostly arises on the server side anyhow and it mostly is a matter of scaling technique difference.

Tanel Suurhans
"JRuby is currently the only Ruby implementation that supports true concurrency": Wrong, IronRuby and MacRuby do as well. "On JVM Ruby threads are mapped to OS native threads": Wrong, both Ruby implementations on the JVM (JRuby and XRuby) map Ruby threads to JVM thready, not native threads. (Mapping to native threads is pretty much impossible on the JVM without masive JNI C hackery.) "So its totally correct to say that Ruby is not multithreaded": Wrong. Just two sentences before this, you actually named a counterexample which invalidates your claim.
Jörg W Mittag
"In 1.8.x Ruby is actually run inside one OS thread": Wrong. Several implementations of Ruby 1.8 use multiple OS threads, for example Rubinius. "[...] green threads [...]": Wrong. There is nothing in Ruby that says you have to use green threads. In fact, there is nothing in Ruby which prescribes any sort of thread implementation, green, native or otherwise. The vast majority of Ruby 1.8 implementations (and Ruby implementations in general) choose not to use green threads, in fact, only a single one does.
Jörg W Mittag
"fake feeling of concurrency with green threads, then in reality GIL will pretty much prevent you from having true concurrency": This one doesn't even make sense. If you have only fake concurrency, then you don't *need* a GIL because there is nothing to protect against concurrent acess, because there *is no concurrency in the first place*. And in fact, the only Ruby implementation which has green threads *does not* have a GIL. The only two implementations which *do* have a GIL are YARV and Rubinius, both of which use native threads.
Jörg W Mittag
"In Ruby 1.9 this changed a bit": Wrong. The threading model in Ruby 1.9 is exactly the same as in Ruby 1.8. There are many changes in Ruby 1.9, like Fibers, Enumerators in the core library, Multilingualization, proc literals, unified argument semantics, but one thing that did *not* change are the threading semantics.
Jörg W Mittag
"In Ruby 1.9 [...], [...] now a Ruby process can have many OS threads attached to it (plus the green threads)" Wrong: the only Ruby implementation which *has* green threads is MRI. And yes, you can have both multiple C threads attached to a single MRI process as well as multiple Ruby threads. But, MRI is an implementation of Ruby 1.8, not Ruby 1.9. *No* implementation of Ruby 1.9 has green threads.
Jörg W Mittag
"[...] but again GIL will totally destroy the point and become the bottleneck." Wrong: MRI doesn't have a GIL. In fact, in MRI, multiple C threads can be running at the same time. Only one Ruby thread can be running but that doesn't have anything to do with a GIL, it is simply a side-effect of the scheduler implementation. Again, the scheduler is *incapable* of scheduling two threads at the same time, so there is no *need* to have GIL to protect the interpreter from multiple threads accessing internal resources at the same time, because there can *never be* multiple threads running anyway.
Jörg W Mittag
Guess Igvita have no clue about what they are doing and telling then. Go figure. http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/
Tanel Suurhans
The author claims in one paragraph that Ruby threads cannot run in parallel and explains in the next paragraph how JRuby runs Ruby threads in parallel. You don't even need to know Ruby to figure out that those two statements are contradictory and thus any article which contains both of those statements simply cannot be true. That's just basic logic: `A ∧ ¬A` simply can *never* be true.
Jörg W Mittag
Guess we didn't read the same article. What i saw was a clear separation of JRuby and MRI/YARV in that discussion. But it's probably not good enough for your nit-picking needs, so be it. P.S You do make valid points, but the way you make it beyond arrogant.
Tanel Suurhans
A: 

Yes Ruby and Python can handle multi-threading, but for many cases (web) is better to rely on the threads generated by the http requests from the client to the server. Even if you generate many threads on a same application to low the runtime cost or to handle many task at time, in a web application case that's usually too much time, no one will wait happily more than some fractions of a second for the response of your application in a single page, it's more wise to use AJAX (Asynchronous JavaScript And XML) techniques: make sure the design of your web shows up rapidly, and make an asynchronous insertion of those hard-coding things later.

That does not mean that multi-threading is useless for web! It's highly recommended to low the charge of your server if you want to run recursive-complicated-hardcore-applications (not for a website, I mean), but what that thing return must end in files or in databases, so then could be softly served by a http response.

sadasant
+2  A: 

A confused question with a lot of confused answers...

First, threading and concurrent execution are different things. Python supports threads just fine; it doesn't support concurrent execution in any real-world implementation. (In all serious implementations, only one VM thread can execute at a time; the many attempts to decouple VM threads have all failed.)

Second, this is irrelevant for web apps. You don't need Python backends to execute concurrently in the same process. You spawn separate processes for each backend, which can then each handle requests in parallel because they're not tied together at all.

Using threads for web backends is a bad idea. Why introduce the perils of threading--locking, race conditions, deadlocks--to something inherently embarrassingly parallel? It's much safer to tuck each backend away in its own isolated process, avoiding the potential for all of these problems.

(There are advantages to sharing memory space--it saves memory, by sharing static code--but that can be solved without threads.)

Glenn Maynard
I'm pretty sure that of the four real-world Python implementations, three *do* support truly concurrent threads. Or, to be more precise, threads synchronized by very fine-grained locks strategically placed around a few very small datastructures instead of a giant monster lock across the entire interpreter.
Jörg W Mittag
It depends on your definition of "real-world", of course, but I won't claim to have tried every implementation either.
Glenn Maynard