How does WordPress ensure plugins run at the same time and how does it solve a plugin’s dependency on another one?

If the plugin indeed runs plugin_1_action as soon as it’s loaded, meaning that the do_action() call is just sitting in the plugin file and not inside a function that’s hooked later, then yes, you’re correct: you won’t be able to hook into it if your plugin is loaded later.

This is almost never how plugins work though. Pretty much all plugins won’t actually run any code as soon as they’re loaded. Plugins will typically hook all their functionality to occur later, usually no earlier than the init hook, which is run after all plugins and themes have loaded.

So let’s say the original plugin has this code:

function og_plugin_initialize() {
    // Does stuff.

    do_action( 'og_plugin_initialized' );
}

This code will probably be hooked to run on the init hook:

add_action( 'init', 'og_plugin_initialize', 20 );

So the og_plugin_initialized hook won’t be executed until the init hook, at priority 20.

If you had a function that you wanted to hook into the og_plugin_initialized hook, then you would add it in your plugin like this:

function my_plugin_init() {
    // Do stuff.
}
add_action( 'og_plugin_initialized', 'my_plugin_init' );

When it’s done like this it doesn’t matter which order the plugins load in, because both plugins and queued up their functions to run later. And since both those functions will run after all plugins have loaded, you can use functions defined in the original plugin without issue.