I would like to add some real-world examples, and connect them to the software engineering world. First, consider something that I hope matches your intuitive definition of "synchronous": the flashing of fireflies, under some circumstances. Second, consider the 4x100 women's Olympic relay race. Third, consider that old trope from military films: "Men, synchronize your watches!"
Now, let's think about what's going on. Let's start out by observing that all of these things are processes, or entities extended in time. It doesn't make sense to say that a bowl is "synchronous" and rock is "async." Second, it takes two to tango. You can't say that "a runner is sync". Sync with what? Finally, in order for two processes to do something at the same time, unless they already have the exact same frequency and phase, one or both of them must wait.
When the dictionary definition says two entities in sync "occur or exist at the same time", that aligns very nicely with the concept of the light from fireflies. Unfortunately, saying that the light is "in sync" is a sloppy way of saying that the firefly lighting processes are synchronized.
So how can a bunch of fireflies, which presumably don't have Apple SmartWatch and NTP to guide them, manage to flash their rear ends at the same time? Well, it's pretty easy if they have a means to set a consistent tempo and can make small adjustments to it. They just flash, and if more folks flash right after them, they slow down (increase the delay), whereas if more flash right before them, they speed up (decrease the delay). So they can use a simple feedback process to arrive at essentially the same tempo and phase. The important observation here is to note that they achieve synchrony by waiting for the right moment to flash.
The 4x100 race is interesting because you see both forms of process timing in action: the runners within a team are synchronized, while the runners on different teams are "async". The second runner in the relay must wait until the first runner enters the transfer zone. The hand-off is a synchronous event between those two runners. However, the runners in different lanes don't care what's happening in another lane, and most certainly don't slow down and do their hand-offs in sync. Each lane of runners is asynchronous with respect to each other. Again, we see that synchronization entails waiting, while asynchrony does not.
Finally, the soldiers in a company (platoon, fire team, etc.) must synchronize their watches so that they can attack the enemy at the same time. It might be that some soldiers arrive at their positions before others, or have an opportunity to fire on the enemy sooner. But a simultaneous attack is generally more effective than a haphazard attack because of the element of surprise. So to achieve synchrony, many of the soldiers must wait for the appointed time to act.
Why this emphasis on waiting? Well, it's because waiting is the defining feature which distinguishes synchronous from asynchronous processes. If you have two processes which you know nothing about, you should, by default, assume that they are asynchronous. For example, a package delivery and an ambulance driving by are most likely not synchronized. In order to demonstrate that two processes are, in fact, synchronized, you need to find a very special moment in time: the synchronization point.
A delivery driver dropping off a package and an ambulance rushing someone to the hospital don't generally share any points in time that we identify as a "synchronization point". On the other hand, fireflies flashing in unison have a sync point every time they flash, relay runners have a sync point every time they hand off the baton, and soldiers have a sync point when they launch their attack. If you can identify one or more sync points, then the processes are synchronized. This should be easy to understand, because "syn-" is a Greek prefix meaning "with" or "together", and "chrono" is the Greek root for "time". "Synchronized" literally means "at the same time", and you should think of it as identifying the existence of synchronization points.
Note that "synchronization" does not necessarily apply to the entire lifetime of either or both processes. I would argue that it only applies to "the waiting time up to and including the synchronization point(s)". Thus, two processes may operate asynchronously until they reach a state where they need to communicate, then they become synchronized, exchange information, and afterwards continue asynchronously. A simple example is meeting someone for coffee. Obviously, the meeting is a synchronization point (or many, rather), and the fact that two people arrive at that point demonstrates the synchrony. However, we would not say that because two people met for coffee, those two human lifetimes are "synchronized". It may be that was the only instant in their lives that they met, and everything else they do is otherwise independent.
It is also not the case that incidental meets demonstrate synchrony. If two strangers pass each other on the street, the fact that they are in a particular place at some time does not prove synchrony. Nor does the fact that one person is sitting on a bench waiting for the bus, and another happens to walk by. Processes are only synchronous when they meet for a purpose.
Now, let's think about a very fundamental task in software: reading from a file. As you probably know, mass storage is usually thousands to millions of times slower than cache or main memory. For this reason, operating systems and programming language libraries generally offer both synchronous and asynchronous I/O operations. Now, even if your program only has a single thread, you should think of the OS as being a "separate process" for the purposes of this discussion.
When you make a "synchronous I/O read", your thread must wait until the data is available, at which point it continues. This is very much like a relay runner handing the baton off to the next runner, but imagine instead a relay with only two runners going all the way round the track, and the second runner also hands off back to the first.
In this case, your program thread and the OS I/O process are not "happening (acting) at the same time", and so it seems weird to say that these processes are "synchronized". But that's the wrong way to look at it! That's like saying: "The runners on a relay team aren't running at the same time, so they aren't synchronized." In fact, both statements are wrong! The runners on a relay team do and must run at the same time, but only at a very specific moment: the hand-off of the baton. In fact, it is only this special moment during the race that convinces us that relay teams are synchronized to begin with! If we view the I/O request and response as "the baton", then it is easy to see that blocking I/O is essentially isomorphic to a 2-woman relay race.
On the other hand, if we think about something like Finite Element Analysis on a supercomputer, we see that thousands of processes must work in lock-step to update a massive global state. Even if some of the nodes complete their work for a given time-step before others, they all need to wait for the time step to complete because the results propagate to neighbors through space. This kind of synchronization is like the fireflies: all actors are performing the same kind of task.
For this reason, we can invent a few terms to help us see that there are three kinds of things going on: "homogeneous synchrony", "heterogeneous synchrony", and "sequential synchrony". So when the actors are performing the same task simultaneously (FEA, fireflies), they are "homogeneous". When they are performing different tasks simultaneously (soldiers running vs. crawling vs. swimming to their destinations, physics vs. sound vs. AI threads in a game), they are "heterogeneous". When they are performing tasks one at a time, they are "sequential" (relay runners, blocking I/O). They may look very different, but they share one essential property: all types of actors perform some waiting to ensure that everyone arrives at the synchronization point at the same time. Whether the actors are "acting" or waiting in between synchronization points, or "performing the same action" is irrelevant to the property of synchronicity.
The render pipelines in a GPU are synchronous because they all must finish the frame together, and start a new frame together. They are homogeneous because they are doing the same kinds of work, and they are all active together. But the main game loop of a server and the blocking I/O threads which process remote input are heterogeneous because they do very different kinds of work, and some of the I/O threads won't be doing anything at all, because not all the connections are used. Even so, they are synchronized, because they must share state atomically (a player must not see a partial game world update, nor must the server see only a fragment of player input).
Now, let's consider an "async I/O read". When your program sends a request to the OS to read a bit of data from storage, the call returns immediately. Let's ignore callbacks and focus on polling. In general, the moment that data is available to your program does not correspond to any special point in time as far as your program's thread is concerned. If your program isn't explicitly waiting for the data, then the thread won't even know exactly when that moment occurs. It will only discover that data is waiting the next time it checks.
There is no special meeting time where the OS and the program thread agree to hand over the data. They are like two ships passing in the night. Asynchrony is characterized by this absence of waiting. Of course, the program thread will often end up waiting on the I/O operation after all, but it doesn't need to. It can happily go on doing other calculations while the I/O fetch is occurring, and only check later when it has a moment to spare. Of course, once the OS is done fetching data, it doesn't sit around waiting, either. It just puts the data somewhere convenient and goes on about its business. In this case, it's like the program hands the baton off to the OS, and the OS comes around later, drops the baton on the ground along with the data, and walks off the track. The program may or may not be waiting around to receive the hand-off.
When we mark a function as "async" in software, it often means we want parallelism. But remember that parallelism does not imply synchrony. The fireflies are a good example, because they, too exhibited both synchronous and asynchronous behavior. While most of the flies flashed in unison, many were obviously out of tune with the rest of the group and flashed more randomly. The flies may have been acting simultaneously, but they were not all synchronized.
Now when we mark some code as "async", it looks funny, because it implies that the rest of the code not so marked is "sync". What does that even mean? Didn't we insist that "synchronization" required two to tango? But what if we are talking about code executing in a single thread? In this case, we need to take a step back and think about a program as a sequence of states and transitions between those states. A statement in a program causes a state transition. We can think of it as a "micro-process" that starts and stops with the statement. The sequence points defined by the language are, in fact, the synchronization points of these "micro-processes". And thus, we can view a single-threaded, serial program as an example of sequential synchrony.
The integrity of the programming language guarantees that state updates don't interfere across statements, and the sequence points define boundaries across which the compiler is not allowed to make observable optimizations. For instance, the order of evaluation of expressions within a statement might be undefined or underspecified, giving the compiler freedom to optimize the statement in a variety of ways. But by the time the next statement begins, the program should be in a well-defined state, if the PL itself is sound.
By now, it should be clear what we mean by "async". It means exactly that the implied contract of synchrony within a block of code is exempted for the async block. It is allowed to update the program state independently, without the guarantees of safety normally implied by the sequential(ly consistent, synchronous) computation model. Of course, this means that we need to take special care that we don't destroy the program state with inconsistency. This usually means that we introduce limited, explicit synchrony to coordinate with the async block. Note that this means the async block can be both asynchronous and synchronous at different times! But recalling that synchronization merely indicates the existence of a sync point, we should have no trouble accepting this notion.