Live data from Hacker News

Java Concurrency – Understanding the Basics of Threads

turkogluc.com

61–70 of 86 posts

Re: Java Concurrency – Understanding the Basics of Threads

#62
post #55

Earlier quoted context omitted.

Excellent example for making my point, since "just wrap it in a transaction" usually leads to concurrency bugs like the beloved lost update.

This is not something I'm familiar with. What's the beloved lost update and what transactions are you using that suffer from it?

Transactions give varying degrees of "isolation" between them, depending on the database (and its version + configuration). For example, in what SQL would call READ COMMITTED, where transactions will only read data that has been committed, read-modify-write updates are generally bugs. The classic example:

    - Intent: both transactions deduct 50 money
    - transaction 1: SELECT balance FROM account; // = 100
    - transaction 2: SELECT balance FROM account: // = 100
    - transaction 1: UPDATE account SET balance = 50
    - transaction 1: COMMIT
    - transaction 2: UPDATE account SET balance = 50
    - transaction 2: COMMIT
    - Result: balance is 50, but should be 0
With serializabile transactions (not all databases have this, particularly if you look beyond SQL):

    - Intent: both transactions deduct 50 money
    - transaction 1: SELECT balance FROM account; // = 100
    - transaction 2: SELECT balance FROM account: // = 100
    - transaction 1: UPDATE account SET balance = 50
    - transaction 1: COMMIT
    - transaction 2: UPDATE account SET balance = 50
    - transaction 2: COMMIT -> Fails, needs to retry
    - transaction 2b: SELECT balance FROM account: // = 50
    - transaction 2b: UPDATE account SET balance = 0
    - transaction 2b: COMMIT -> Ok!
    - Result: balance is 0
Because this is needed so frequently, databases have calculated updates, basically atomic operations:

    - transaction 1: UPDATE account SET balance = balance - 50; // values indeterminate
    - transaction 2: UPDATE account SET balance = balance - 50; // values indeterminate
    - transactions 1,2: COMMIT
    - Result: balance is 0
Or, one could lock the rows, like so:

    - transaction 1: SELECT FOR UPDATE balance FROM account; // = 100
    - transaction 2: SELECT FOR UPDATE balance FROM account: // = transaction 2 is stalled until transaction 1 commits or rollbacks
    - transaction 1: UPDATE account SET balance = 50
    - transaction 1: COMMIT
    // transaction 2 can now continue and gets balance = 50
    - transaction 2: UPDATE account SET balance = 00
    - transaction 2: COMMIT
    - Result: balance is 0
And this is just one simple example of the problems you can have concurrently accessing one table, even while using transactions. Not to speak of the issues you can run into when interacting with systems outside a single database, which don't interact with the transaction semantics of the DB.

Concurrency is just very non-trivial regardless the abstraction.

Re: Java Concurrency – Understanding the Basics of Threads

#63
post #53
post #46

Earlier quoted context omitted.

And yet we're comfortable hand-waving GOTO away - that is, not calling computers GOTO machines.

There are thousands of engineers (at least) who use it or its equivalent every day. Just because they’ve built abstractions that allow you to ignore it, doesn’t mean nobody has to deal with it anymore.

But that's identical to what he's saying; he's not saying no one has to deal with mutable memory. Just that most developers who need concurrency shouldn't have to. Same as registers, GOTO, etc.

Re: Java Concurrency – Understanding the Basics of Threads

#64
post #4

The problem is not the threads, it is the mutations of variables which boost the complexity of the code. So a tutorial on creation of theads actually an invitation to hell. Nothing is cool about it. Cool thing is achieving concurrency without threads/race conditions/shared memory

Do you use other paradigm / languages ? (clojure comes to mind, but maybe others)

I'll add Pony to the list. This language uses the actor model like Akka and Erlang, but allows for the safe sharing of data between actors enforced by an an ingenious use of the type system. The result is an actor programming model with better performance than Erlang because mutable data can be safely shared.

I have been a long time Java developer, and I have worked a lot with highly concurrent code. Pony really opened my eyes to what was possible.

Unfortunately, the language, standard library and runtime is still pretty immature. It does however have very good 'C' interop. So for some problems it would be a very good fit.

Re: Java Concurrency – Understanding the Basics of Threads

#65
post #23

With Futures and Executors/ExecutorServices I find that I rarely ever need to use raw Threads these days. Most of the thread-safety issues commonly encountered are eliminated with this approach as well.

Likewise, with futures and executors I haven't had to touch threads directly for some time. They give you the tools to just say "go away and do these things", which after years of dealing directly with pthreads in C was a breath of fresh air!

But compare this very recent submission: https://news.ycombinator.com/item?id=24921657

which presents threads as the solution to the pain of using futures.

Re: Java Concurrency – Understanding the Basics of Threads

#66
post #53

Earlier quoted context omitted.

There are thousands of engineers (at least) who use it or its equivalent every day. Just because they’ve built abstractions that allow you to ignore it, doesn’t mean nobody has to deal with it anymore.

But that's identical to what he's saying; he's not saying no one has to deal with mutable memory. Just that most developers who need concurrency shouldn't have to. Same as registers, GOTO, etc.

That's not what they said. They said "nothing is cool about a tutorial on creation of threads", and that the cool thing is "achieving concurrency without threads/race conditions/shared memory" which ironically is only enabled by all the engineers who spend their time working on and maintaining those "uncool" things.

If they don't need to use threads, then good for them. But to dismiss threads and learning material about threads as "uncool" is just silly. The thing that enables that misunderstanding is all the work that's done on them in the first place.

Re: Java Concurrency – Understanding the Basics of Threads

#67
post #19

Years ago, I tried learning how to use threads by following tutorials similar to this one, where you are taught how to implement threads from {python, java, c++}. However, it wasn't until I studied operating systems (when I returned to graduate school for computer science) was I able to wrap my mind around threads — from a language agnostic view point, how and what lightweight processes are, how to implement locks an…

Seconded. It’s silly to learn threads “from the outside in” — thinking of them as an opaque abstraction and trying to understand the API they present. There’s no coherent abstraction there; you’ll only learn to cargo-cult the API, without gaining an intuition for what threads “are” or when and where you’d want to use those APIs. The key thing to know, is that threads aren’t a first-class kernel object. In OS kernels,…

I know about unix/linux processes, ipc and the relevant system calls (exec*, fork, clone, ...) but where do I continue from there?

Studying C, I haven't really come across threads other than trying out the things in `pthread.h`.

Would you recommend just reading the source code of that header for a better understanding?

Re: Java Concurrency – Understanding the Basics of Threads

#69
post #51

Earlier quoted context omitted.

What's a better alternative to synchronizing access to shared resources?

Treat it like GC and don't leave it up to the programmer.

Does that involve using concurrency primatives that basically don't allow access to any shared mutable state?

Re: Java Concurrency – Understanding the Basics of Threads

#70
post #6
post #4

The problem is not the threads, it is the mutations of variables which boost the complexity of the code. So a tutorial on creation of theads actually an invitation to hell. Nothing is cool about it. Cool thing is achieving concurrency without threads/race conditions/shared memory

The concepts of threads and concurrent data access is simple enough for any decent programmer to comprehend. There is no hell here. Sure there are some complex cases but complex cases will arise in many situations when programming things. And achieving concurrency without shared memory is impossible in general case. Sure it is possible to isolate such access to a separate layer and make it transparent for the rest of…

> The concepts of threads and concurrent data access is simple enough for any decent programmer to comprehend. There is no hell here.

It's notoriously difficult to reason about concurrent programs using intuition. Much more difficult than reasoning about non-concurrent imperative code. This is why there are articles like [0], and why a bug in a Wikipedia article on a fundamental concurrency algorithm went unnoticed until an analysis tool detected the issue, [1] and why lock-free algorithms in particular are so tricky to get right.

[0] https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedL...

[1] [PDF] https://llvm.org/pubs/2008-08-SPIN-Pancam.pdf

Post reply on HN