back
83 comments
I'm a little disappointed in the name because latch already has a specific meaning for computer engineers. It is one of the first memory circuits we study and forms the basis for registers.
Not meaning to disregard your point, but the class doing the same thing as `std::latch` in the JDK is called `CountDownLatch`[1] and is used in a similar way:

    CountDownLatch workDone = new CountDownLatch(6);
    workDone.countDown(); // mark an event
    workDone.await(); // wait until the counter reaches zero
Even if latches also refer to another concept, it's still positive to see some naming consistency across languages. What name would you have preferred?

[1] https://docs.oracle.com/en/java/javase/11/docs/api/java.base...

That's a barrier.

A latch is a circuit that takes on a value (high or low, 1 or 0) when some some gating signal arrives (like a clock pulse) and then holds that value after the input is removed.

It is named after a door latch; a door latches when you close it and then holds that state: you can't pull it open again without using the handle/knob.

If something is called "latch" which does not change its state once in order to reflect an input event, and then hold that state until explicitly recent, then it's misnamed due to abusing the metaphor.

The barrier metaphor is the right one for an object that is hit some predetermined number of times and then fires an event (like releasing some waiting thread(s)). That predetermined number of events is its "barrier potential": the threshold that must be met to break through the barrier.

I have limited knowledge of the Java and C++ libraries but I believe Go has something similar called a WaitGroup.
Had a mentor who said one of the biggest problems in computer science is that all the good metaphors are already taken.
But in this case the concept already had a name in CS and it was called a barrier (which is a pretty apt name too). For some rename they called it a latch and then they called a cyclic barrier a barrier...
I don't know who said the following, but it sums up CS pretty good:

"There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors."

It's interesting how we've used all the various 'doing' words in English for different technical concepts, although with some overlap. Function, method, procedure, action, operation, routine, task, process.
Note the name isn't new for this concept, Java also uses the latch name to describe this: https://docs.oracle.com/javase/7/docs/api/java/util/concurre...
Apparently databases historically call shared-memory locks "latches" to distinguish them from locks used for transaction conflict detection.
Yeah this confused me too. Not sure what made them think this resembles a latch. A latch only has 2 states, not 2^n states.
The full name is typically CountDownLatch [0]. The latch still has 2 states, closed and open. It's just that it doesn't open until everyone is ready.

[0] https://docs.oracle.com/en/java/javase/15/docs/api/java.base...

The name makes a bit of sense, in the sense that once it's signaled, it stays that way. So the signaled state is latched.

This contrasts to std::barrier which auto-resets once signaled[1].

As such I think it would be better if they had called it std::latched_barrier or similar.

[1]: https://en.cppreference.com/w/cpp/thread/barrier

And barrier instructions/semantics are used by many architectures to flush/partition pipelines. AFAICT this one doesn't do that.

Too bad they couldn't qualify it somewhere further down below std::. Something like std::thread::barrier or similar might be easier to understand.

It will also be annoying for HW designers ... latches and flip-flops have a very specific meaning in their world.
The name has been overloaded ;)
It sounds like "latch" is basically the same thing as an "event" (as in CreateEvent() in Windows, eventfd in Linux), but maybe optimized for single-process usage?

Edit: Ok so a (Windows) event is one bit, a C++ latch is a one-shot counter, and a C++ barrier is a cyclic counter. But I thought a barrier in general computer science terms is just a one-shot counter, which is what they're calling a latch in C++?

Does someone have any idea why latches do not have also count up operation alongside count down? In one of my previous jobs, I implemented a latch with a mutex, condition variable, and a counter and I supported also count up. It seems to work OK and count up was an essential operation for the use case I had needed it.

    class ThreadLatch
    {
    public:
        ThreadLatch(std::size_t count = 0)
            : _count(count) {}

        void inc()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            ++_count;
        }

        void dec()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            assert(0 != _count);
            --_count;
            if(0 == _count)
            {
                _condition.notify_all();
            }
        }

        void wait()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            while(_count > 0)
            {
                _condition.wait(lock);
            }
        }

    private:
        std::mutex _mutex;
        std::condition_variable _condition;
        std::size_t _count;
    };
What's the difference with a semaphore?
A semaphore can be used to control thread access to a resource.

A latch allows one or more threads to wait until a set of operations being performed in other threads completes [0].

[0] https://docs.oracle.com/javase/8/docs/api/java/util/concurre...

A semaphore allows threads to pass until the counter reaches zero.

A barrier (what this thing is) blocks threads until the counter reaches zero.

Why use the bank account example to introduce a problem and then never resolve it with latches?
How are latches implemented? Is it more efficient than just a condition variable?
Check out futexes [1]. I did a quick scan of the llvm libcxx sources and latch and other threading primitives are based on this syscall.

[1] https://en.wikipedia.org/wiki/Futex

Right, and futexes also back condition variables in glibc.
Probably atomic increment / decrement + condition_variable. Just check if you hit 0 on decrement to notify waiters (or return if you are the waiter).
Well now that sounds like a semaphore!
Almost certainly. Condition variables are very complicated internally. On Linux, a latch could be backed by a futex with very little code.
What is the source of the complexity inside condition variables? Reading the glibc sources, the main problem seems to be ensuring that signals are delivered properly?
Typical implementations use std::atomic or a variation of it (further stripped version of it).
"When you think about this workflow, you may notice that it can be performed without a boss." hehe
Is that just the same as

    ws.Add(1)
    [...]
    wg.Done() 
in Go?
In most cases I think they're identical. WaitGroup has an ability that latch doesn't: WaitGroup can Add() and subtract (Add() with negative) whereas latch can only subtract (latch has to be initialized with its maximum value). The fact that latch is initialized with its value could be a little more convenient than WaitGroup in some situations (save 1 line of code). latch has an ability that WaitGroup doesn't: .try_wait(). Also latch's .arrive_and_wait() can save a line of code compared to WaitGroup.
Go's approach seems a little more prone to user error. I know I've been tripped up by not explicitly adding a worker.
Saving lines of code in C++ compared to Go is like fighting windmills.
Small typo above but it seems like a different approach to mutex. What's similar is basically a count of operations that's locked between threads/routines.
Haha yes sorry, a Freudian slip of me working with web sockets at the moment.
Does the Java ecosystem offer something similar?
Isn't CountDownLatch [0] the same thing in Java?

[0]: https://docs.oracle.com/javase/7/docs/api/java/util/concurre...

It is exactly that.
I love multithreading. So much fun.
And that's why I love Java. Somehow it's been there for almost 20 years.
Worth noting Doug Lee's early work on adding concurrency to Java. That effort resulted in the java.util.concurrency package but work started in the late nineties and it was available as a separate library. And of course it included a Latch class; and the related CountDownLatch.

http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/co...

Before this stuff landed, Java's concurrency model was a lot less nice to deal with. Good high level abstractions are important. Nice to see the same kind of primitives are being added to C++.

Glib::Cond has existed for longer, and is just a wrapper around pthread condition variables that go back to the 1980s.

Several other C++ libraries also provided condition variables, which latches are a variant of, along with barriers and flex_latches.

Why I like Java, by Mark Dominus https://blog.plover.com/prog/Java.html

"I enjoyed programming in Java, and being relieved of the responsibility for producing a quality product."

Very poorly and confusingly named.