right?
The comments (I haven't paid attention to them at first) are great. People are saying good things. Especially, "Vishwa Bhat" and "Sébastien Portebois's". Particularly, Sebastien said my main thought:
"but as a developer, it makes a huge difference because as a developer you don’t have to think about how the memory will be managed, you focus on how you design the logic. And I believe this is the key idea: threads are an implementation decision, whereas goroutines and channels are a design decision: you build for concurrency, even if it doesn’t run in parallel."
This is the main advantage about coroutines that are integrated into the language. The things you've mentioned in the article are mostly irrelevant. Exept memory footprint probably: having 1000 coroutines with 16MB footprint is really cool. However, this is not really true measurement, but anyway, this is very important point to mention. All other things almost make no difference.
So the main idea: in java you have to put an effort and design system specifically to be massively parallelized; in go this is the automatic feature of coroutines built into the language.
Again, in java stack size is almost irrelevant, very little amount of data is passed with stack - only primitive types (boolean - 1byte, int - 4bytes, long - 8bytes, and most often - pointers 4-8bytes). Unlike C/C++ there's no such concept as allocate object/struct on stack. So stack size is not a limiting factor in real life in java.
Number of threads. Technically, you can write an app from scratch that spawns new thread for each new task it is doing (serve a client, run async db call, etc.). Then you'll definitely run in mentioned problem. But nobody does this. All the frameworks, libs, tools use different approach. (that is by the way the main reason why I suggested to use netty even for most simple http server for @vincent7 - you don't need to organize concurrency yourself). And a live java app under load doesn't spawn 1000 threads. It is a good and well known practice to use (!ding!) schedulers, or "executors" in java terminology. They do almost the same job as go's internal scheduler, but in java it is much worse and limited. Here's key concepts: 1) executor abstracts away usage of threads, it spawns them according to its strategy (different implementations are available, like "single", "cached", "fixed sized" - mostly used, etc) 2) tasks are pushed/scheduled to executor's task queue, and it runs those tasks on thread when thread is free 3) os scheduler manages when and how much cpu time to give to active threads. What are the main cons: 1) task is indivisible unit of work - when it was assigned to the thread, it can't be paused/put off/assigned back/resumed, i.e. thread will execute it until task is finished 2) as a result, developer should put effort in design of those tasks, deciding what piece of work should be atomic - this is horrible in practice. However, tasks, even if there's a 1 million of them to be run are pushed to queue and wait their time when they are assigned to thread to be run. And there could be 20 threads for example serving as runners for those 1 mln of tasks. In theory, there even could be 9 threads on 8-core system to serve those 1mln tasks efficiently if there would be no interrelated tasks (waiting for result from another task). This is well known technique in java. Nobody spawns threads in practice, just use thread pool. And task queue is stored in heap, so stack is not involved. To put it simple, in java 1000 clients (or any other number of clients) may be served well by several dozens of threads.
This is the thing that I would highlight in such article. This is more important and demonstrates how great go coroutines are comparing to java's concurrency. By the way, in java there's similar mechanism to go's channels, but I haven't ever seen that anyone used them with vanilla tread-based tasks (not in coroutines or actors frameworks).
I finally understand what can be easily achieved through golang compare to java when I have to make an application that has to do several long running processes which are triggered through web api invoke and delivery of real time execution results at any time through the push mechanism from the web server to the client using web socket communication and this app must be designed to handle massive request
Обсуждают сегодня