Within one instance of your application, this will never happen, due to the fact that the Repository which is used to load your Aggregate prior to giving it the command the handle, will place a lock on it.
Hence two (or more) distinct commands being published at the same aggregate concurrently, within the same instance of your application, will wait for one another.
Between instances of your application, this is a different story though, as we do not use a distributed locking mechanism on the Aggregates.
What instead would happen, is that if two (or more) distinct commands are targeted to the same Aggregate instance, but done so by different instances of your application, that the given Aggregate instance would be loaded by both.
However, you’d typically publish events upon handling commands. These events have a unique constraint in the store based on the Aggregate Identifier and the event’s sequence number.
Thus, if the above scenario would occur, you’d still have one of the instances being the fastest in to publishing the event in the store.
Due to the constraint, the second command handler would fail with a ConcurrencyException, as it could not store an event for the Aggregate on the given sequence number, as it already exists.
To overcome commands for one aggregate being handled by two (or more) different instances of your application, you could simply use Axon Server to do the routing for you.
The DistributedCommandBus in the core package also has functionality to ensure commands for one aggregate are always routed to the same instance.
So, typically, you’re ensured this issue will be resolved for you.
Hope this helps!