www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What are the real advantages that D offers in multithreading?

reply nbro <blah gfail.com> writes:
Hi!

I have seen that D offers basically similar constructs to Java 
for example for creating multithreaded applications. I would like 
to understand better what are the real advantages that D offers. 
Does D offer something that other known programming languages, 
such as C++, Java and Python, do not offer? An exhaustive 
explanation with concrete examples would be nice.
Jan 26 2016
next sibling parent reply nbro <blah gfail.com> writes:
On Tuesday, 26 January 2016 at 11:41:49 UTC, nbro wrote:
 Hi!

 I have seen that D offers basically similar constructs to Java 
 for example for creating multithreaded applications. I would 
 like to understand better what are the real advantages that D 
 offers. Does D offer something that other known programming 
 languages, such as C++, Java and Python, do not offer? An 
 exhaustive explanation with concrete examples would be nice.
Moreover, could you also explain why D was designed to synchronize entire classes instead of single methods. If I synchronize single methods (in Java for example), I could still be able to use other non-synchronized methods without needing to acquire the lock, so I don't understand this decision.
Jan 26 2016
next sibling parent Guillaume Piolat <contact gam3sfrommars.fr> writes:
On Tuesday, 26 January 2016 at 11:44:56 UTC, nbro wrote:
 On Tuesday, 26 January 2016 at 11:41:49 UTC, nbro wrote:
 Hi!

 I have seen that D offers basically similar constructs to Java 
 for example for creating multithreaded applications. I would 
 like to understand better what are the real advantages that D 
 offers. Does D offer something that other known programming 
 languages, such as C++, Java and Python, do not offer? An 
 exhaustive explanation with concrete examples would be nice.
Moreover, could you also explain why D was designed to synchronize entire classes instead of single methods. If I synchronize single methods (in Java for example), I could still be able to use other non-synchronized methods without needing to acquire the lock, so I don't understand this decision.
On the practical side: - D has easy parallel foreach in the standard library. - D has easy TLS variables which can help in caching situations from time to time (avoids a contention point). Not sure what they are for else. - D has pure which helps compiler disambiguate aliasing (a pure function couldn't touch anything else that what is passed.) On the "not sure if useful" side: - D has a GC which helps in some lock-free situations. - D has deep-const and immutable which can be shared between threads without restrictions. - D offers "shared" which can theorically help you signal things that are shared between threads. - synchronized classes and methods. But they are more a liability that a positive, you can always make something finer-grained with a mutex.
Jan 26 2016
prev sibling next sibling parent reply Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 2016-01-26 at 11:44 +0000, nbro via Digitalmars-d wrote:
=20
[=E2=80=A6]
 Moreover, could you also explain why D was designed to=C2=A0
 synchronize entire classes instead of single methods. If I=C2=A0
 synchronize single methods (in Java for example), I could still=C2=A0
 be able to use other non-synchronized methods without needing to=C2=A0
 acquire the lock, so I don't understand this decision.
It should be pointed out that anyone using the synchronized keyword anywhere in Java code is doing concurrent and parallel programming wrong. If they are using synchronized in single threaded programming well, then=E2=80=A6 The issue here is Java monitors, which are massively overweight, and have been since 1994. Indeed the whole wait/notify system is a serious problem. Sadly it took 20 years for people at the heart of Java development to finally admit this in (semi-)public. Doug Lea's, Brian Goetz, and others have over the last 10 years been making things better. A lot better. So good concurrent and parallel Java eshews synchronized, wait and notify, and employs one or more of the thread safe parallel data structure, e.g. ConcurrentHashMap, the futures related things, or more usually now Streams. synchronized, wait and notify along with the lock and monitors should be deprecated and removed. =C2=A0 Sadly as we know nothing that is deprecated ever gets removed from Java. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jan 28 2016
next sibling parent reply nbro <blah gfail.com> writes:
On Thursday, 28 January 2016 at 11:53:48 UTC, Russel Winder wrote:
 On Tue, 2016-01-26 at 11:44 +0000, nbro via Digitalmars-d wrote:
 It should be pointed out that anyone using the synchronized 
 keyword anywhere in Java code is doing concurrent and parallel 
 programming wrong. If they are using synchronized in single 
 threaded programming well, then…

 The issue here is Java monitors, which are massively 
 overweight, and have been since 1994. Indeed the whole 
 wait/notify system is a serious problem. Sadly it took 20 years 
 for people at the heart of Java development to finally admit 
 this in (semi-)public. Doug Lea's, Brian Goetz, and others have 
 over the last 10 years been making things better. A lot better.

 So good concurrent and parallel Java eshews synchronized, wait 
 and notify, and employs one or more of the thread safe parallel 
 data structure, e.g. ConcurrentHashMap, the futures related 
 things, or more usually now Streams.

 synchronized, wait and notify along with the lock and monitors 
 should be deprecated and removed.

 Sadly as we know nothing that is deprecated ever gets removed 
 from Java.
I don't understand why you say that everyone that uses synchronized is doing bad concurrent programming. That's not correct, if you know how to use it. Also, I don't understand why also lock and monitors should be removed. How would you write then multithreaded programs?
Jan 28 2016
parent Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Thu, 2016-01-28 at 22:38 +0000, nbro via Digitalmars-d wrote:
=20
[=E2=80=A6]
 I don't understand why you say that everyone that uses=C2=A0
 synchronized is doing bad concurrent programming. That's not=C2=A0
 correct, if you know how to use it. Also, I don't understand why=C2=A0
 also lock and monitors should be removed. How would you write=C2=A0
 then multithreaded programs?
<Also hopefully fulfilling cym13's request for more detail.> If a programming language imposes the overhead of concurrency management on all and every thing involved, then you have a huge overhead =E2=80=93 even if it is not used, or even known about. In the Java context, the whole object lock, wait, notify, notifyAll was well intentioned in 1992=E2=80=931995, but in hindsight was the wrong thing= to do. But to then impose monitor overhead (synchronized keyword on methods) and to use it in the standard library everywhere, cf. StringBuffer vs. StringBuilder, was rather silly. Hence the whole sad history of the Java collections library, and it's somewhat farcical iterators. Thiez nicely summarized the next level of detail about the problems with the Java object lock system, so I will avoid repeating that here. The summary is that the standard Java object locks system is fundamentally flawed, and should not be used. Sadly it is going to be impossible to ever get away from it being part of the Java Platform. So what is the way forward. This is many-fold: 1. Study the java.util.concurrent package set and use the concurrent data structures available. 2. Study the java.util.concurrent package set and note the existence of threadpools. Use asynchronous calls and futures. Use thread safe queues to communicate and coordinate. 3. Use higher level abstractions such as actors, dataflow, CSP (concurrent sequential process), active object, picoservices, etc. to structure your code so as to avoid any an all explicit threads and locks. Look at Akka, Quasar, GPars, for example frameworks. Only people writing operating systems (or OS level "applications", usually embedded systems on very constrained devices) should ever need to worry about stack management, thread managment, etc. Everyone else should be using higher-level abstractions built over the infrastructure. Programming is about abstraction. Threads, language stacks, etc. are the wrong abstraction level for almost all applications programming, and most system programming. The single biggest lesson that Go has brought front and centre (not center, obviously) is that collections of sequential processes communicating using channels is a very successful and easy to program way of building extremely concurrent and parallel systems. Of course this is something the HPC people have known for 35+ years since they never got sidetracked by shared memory multithreading as a programming architecture. Shared memory multithreading is an operating systems architecture, developed for writing operating systems. There is no reason why we should continue to thing of the concurrency and parallelism theory of operating systems as the one and only way of programming applications. Whatever the 1990s and 2000s have said on architecting applications, the 1960s model of actors, 1970s model of dataflow, and 1980s model of CSP are far better architectural models for creating highly concurrent and parallel applications and systems programs.=C2=A0 =C2=A0 =C2=A0 --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Feb 04 2016
prev sibling parent reply cym13 <cpicard openmailbox.org> writes:
On Thursday, 28 January 2016 at 11:53:48 UTC, Russel Winder wrote:
 It should be pointed out that anyone using the synchronized 
 keyword anywhere in Java code is doing concurrent and parallel 
 programming wrong. If they are using synchronized in single 
 threaded programming well, then…

 [...]
I have seen you talk about this before and I too would love you to elaborate on the subject.
Jan 28 2016
parent Thiez <thiezz gmail.com> writes:
On Thursday, 28 January 2016 at 22:59:58 UTC, cym13 wrote:
 On Thursday, 28 January 2016 at 11:53:48 UTC, Russel Winder 
 wrote:
 It should be pointed out that anyone using the synchronized 
 keyword anywhere in Java code is doing concurrent and parallel 
 programming wrong. If they are using synchronized in single 
 threaded programming well, then…

 [...]
I have seen you talk about this before and I too would love you to elaborate on the subject.
One of the most obvious problems with using `synchronized` on methods, or using `synchronized(this)`, is that an object has no control over its monitor. All code that can see a particular instance can choose to synchronize on that instance, which creates opportunities for deadlocks. This problem can be avoided by controlling access to the monitor you use. One of the easiest ways to control access to your monitor is by having a private object to synchronize on (e.g. `private final Object lock = new Object();`) instead of synchronizing on `this`. Further improvements can be made by explicitly using one of the classes found in java.util.concurrent.locks: this allows you to be more explicit by, for instance, choosing a ReadWriteLock, and it provides access to proper conditions. Another problem with `synchronized` in Java is that it requires all objects to contain an implicit monitor, while the vast majority of objects will never get synchronized on: for all those objects this is useless overhead. Sadly backwards compatibility implies that Java will likely never be able to entirely get rid of this overhead.
Jan 29 2016
prev sibling parent cym13 <cpicard openmailbox.org> writes:
On Tuesday, 26 January 2016 at 11:44:56 UTC, nbro wrote:
 On Tuesday, 26 January 2016 at 11:41:49 UTC, nbro wrote:
 Hi!

 I have seen that D offers basically similar constructs to Java 
 for example for creating multithreaded applications. I would 
 like to understand better what are the real advantages that D 
 offers. Does D offer something that other known programming 
 languages, such as C++, Java and Python, do not offer? An 
 exhaustive explanation with concrete examples would be nice.
Moreover, could you also explain why D was designed to synchronize entire classes instead of single methods. If I synchronize single methods (in Java for example), I could still be able to use other non-synchronized methods without needing to acquire the lock, so I don't understand this decision.
I don't know what was the decisive point of the decision but in can't help but note that it makes a lot of sense because D has functions. Object methods are meant to be used with the encapsulated data. If it doesn't touch those data then it must be a function, it has nothing to do as a method. If it does touch those data then in multithreaded applications synchronizing only one amongst others doesn't make any sense: encapsulated data is a share resource. In java you don't have functions, only methods, so I sort-of understand why they did it that way. But in any other (sane?) language functions should be decoupled from methods anyway.
Jan 28 2016
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
D differs in how threads share data. See last chapters of 
tutorial: http://ddili.org/ders/d.en/index.html from 
"Parallelism" to "Fibers".
Jan 26 2016
parent bachmeier <no spam.com> writes:
On Tuesday, 26 January 2016 at 12:47:24 UTC, Kagamin wrote:
 D differs in how threads share data. See last chapters of 
 tutorial: http://ddili.org/ders/d.en/index.html from 
 "Parallelism" to "Fibers".
Also, the start of chapter 11 of Learning D has a discussion of these issues, and links to http://www.informit.com/articles/printerfriendly/1609144 (chapter of Andrei's book) and http://octarineparrot.com/article/view/getting-more-fiber-in-your-diet (article).
Jan 26 2016
prev sibling next sibling parent w0rp <devw0rp gmail.com> writes:
The most important thing D does, which is fundamentally 
different, is that variables are thread local by default, and you 
must opt-in to variables that are shared across threads. 
Immutable data can be shared implicitly, because there are no 
writers. This means that if you keep only a small amount of 
shared state, it should be easy to track down what could possibly 
be affected by multi-threading issues.

I haven't ever used synchronized classes myself, but it's 
probably a way of preventing mistakes where you synchronize some 
methods, but not others. You can also use synchronized {} blocks 
to introduce some recursive locking for a series of statements. 
So you could put that inside of a class method.
Jan 26 2016
prev sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Tue, 26 Jan 2016 11:41:49 +0000, nbro wrote:
 Does D
 offer something that other known programming languages, such as C++,
 Java and Python, do not offer?
D has in the standard runtime Fibers (aka coroutines). You can use fibers in C++ if you find a library to do it (boost might?). You might be able to find a Java library for it, but it's difficult and might require bytecode rewriting. I think pypy has coroutines. But on the whole, it's a bear to find working coroutines in most languages. Go has "goroutines", which are effectively coroutines that are entirely hidden from you. If you need to manage scheduling yourself, or you need to ensure that a particular thing is running all the time, this really isn't an option in Go.
Jan 26 2016
next sibling parent reply Kagamin <spam here.lot> writes:
On Tuesday, 26 January 2016 at 20:33:34 UTC, Chris Wright wrote:
 You can use fibers in C++ if you find a library to do it (boost 
 might?). You might be able to find a Java library for it, but 
 it's difficult and might require bytecode rewriting.
The java approach is Netty and NIO.
Jan 27 2016
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Wednesday, 27 January 2016 at 09:33:16 UTC, Kagamin wrote:
 On Tuesday, 26 January 2016 at 20:33:34 UTC, Chris Wright wrote:
 You can use fibers in C++ if you find a library to do it 
 (boost might?). You might be able to find a Java library for 
 it, but it's difficult and might require bytecode rewriting.
The java approach is Netty and NIO.
Netty and NIO are an event dispatching mechanism (think libebevent) backed by a ForkJoinPool. No fibers there. Java /does/ have fibers in Quasar, though the implementation is a bit weird because the Java instruction set doesn't support continuations. Message passing via std.concurrency is important to note. The scheduler is pluggable and can seamlessly multiplex fibers on top of a thread pool (the Erlang "millions of threads" approach). Thread local by default is notable as well, though fibers throw a wrench in this. The "synchronized" keyword is inadvisable in modern concurrent programming. I think it remains largely to ease porting code from Java.
Jan 30 2016
parent Kagamin <spam here.lot> writes:
On Saturday, 30 January 2016 at 17:46:35 UTC, Sean Kelly wrote:
 Netty and NIO are an event dispatching mechanism (think 
 libebevent) backed by a ForkJoinPool. No fibers there. Java 
 /does/ have fibers in Quasar, though the implementation is a 
 bit weird because the Java instruction set doesn't support 
 continuations.
I mean approach to the same problem of handling of many requests, that fibers are used for in vibe.d.
Feb 01 2016
prev sibling parent reply Brad Anderson <eco gnuk.net> writes:
On Tuesday, 26 January 2016 at 20:33:34 UTC, Chris Wright wrote:
 On Tue, 26 Jan 2016 11:41:49 +0000, nbro wrote:
 Does D
 offer something that other known programming languages, such 
 as C++,
 Java and Python, do not offer?
D has in the standard runtime Fibers (aka coroutines). You can use fibers in C++ if you find a library to do it (boost might?). You might be able to find a Java library for it, but it's difficult and might require bytecode rewriting. I think pypy has coroutines. But on the whole, it's a bear to find working coroutines in most languages. Go has "goroutines", which are effectively coroutines that are entirely hidden from you. If you need to manage scheduling yourself, or you need to ensure that a particular thing is running all the time, this really isn't an option in Go.
Yeah, boost can do fibers. ASIO has clever/hacky "stackless coroutines" and C++17 is going to add "stackless resumable functions" for async/await. D is about to lose a competitive advantage here.
Jan 27 2016
next sibling parent reply Kagamin <spam here.lot> writes:
On Wednesday, 27 January 2016 at 17:30:28 UTC, Brad Anderson 
wrote:
 Yeah, boost can do fibers. ASIO has clever/hacky "stackless 
 coroutines" and C++17 is going to add "stackless resumable 
 functions" for async/await. D is about to lose a competitive 
 advantage here.
Isn't asio based on fibers just like vibe?
Jan 28 2016
next sibling parent deadalnix <deadalnix gmail.com> writes:
On Thursday, 28 January 2016 at 10:26:29 UTC, Kagamin wrote:
 On Wednesday, 27 January 2016 at 17:30:28 UTC, Brad Anderson 
 wrote:
 Yeah, boost can do fibers. ASIO has clever/hacky "stackless 
 coroutines" and C++17 is going to add "stackless resumable 
 functions" for async/await. D is about to lose a competitive 
 advantage here.
Isn't asio based on fibers just like vibe?
strategies can be used concurrently. For instance, HHVM run each request in a fiber + use asio within request to get another level of parallelism.
Jan 28 2016
prev sibling parent Brad Anderson <eco gnuk.net> writes:
On Thursday, 28 January 2016 at 10:26:29 UTC, Kagamin wrote:
 On Wednesday, 27 January 2016 at 17:30:28 UTC, Brad Anderson 
 wrote:
 Yeah, boost can do fibers. ASIO has clever/hacky "stackless 
 coroutines" and C++17 is going to add "stackless resumable 
 functions" for async/await. D is about to lose a competitive 
 advantage here.
Isn't asio based on fibers just like vibe?
No, it's primarily a callback oriented interface. Boost.Fiber (which is relatively new) added some stuff so you could use something more like vibe.d with ASIO. ASIO has had a "stackless coroutine" option since 1.42, I think. They are, like I said, very clever and hacky. It uses preprocessor macros to define new "keywords". They use switches and loops under the hood to appears as coroutines[1]. It's an impressive idea but language supported coroutines would be a lot better. ASIO is serving as the basis for C++17's network library. The co-routines are still being argued about but if the design gets nailed down before then I'm sure the C++17 networking library will make use of the feature. 1. http://www.boost.org/doc/libs/1_56_0/boost/asio/coroutine.hpp
Jan 28 2016
prev sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Wed, 27 Jan 2016 17:30:28 +0000, Brad Anderson wrote:

 Yeah, boost can do fibers. ASIO has clever/hacky "stackless coroutines"
 and C++17 is going to add "stackless resumable functions" for
 async/await. D is about to lose a competitive advantage here.
I looked at those stackless coroutines. They're nowhere near good enough for what I wanted to do. You can't use them for a vibe-like framework. But they're still called coroutines, so D's going to lose a marketing advantage.
Jan 28 2016
parent Brad Anderson <eco gnuk.net> writes:
On Thursday, 28 January 2016 at 17:21:21 UTC, Chris Wright wrote:
 On Wed, 27 Jan 2016 17:30:28 +0000, Brad Anderson wrote:

 Yeah, boost can do fibers. ASIO has clever/hacky "stackless 
 coroutines" and C++17 is going to add "stackless resumable 
 functions" for async/await. D is about to lose a competitive 
 advantage here.
I looked at those stackless coroutines. They're nowhere near good enough for what I wanted to do. You can't use them for a vibe-like framework. But they're still called coroutines, so D's going to lose a marketing advantage.
They aren't fit for every task, of course. They've been discussed here on the NG in the past: http://forum.dlang.org/thread/izosaywbnlxnbzyhjbnu forum.dlang.org
Jan 28 2016