Phase 1, canCommit: the coordinator asks every participant whether it can commit. Each participant checks constraints, locks rows, and replies yes or no. Nobody has written anything permanent yet. A single no, or a timeout, leads straight to a global abort.
Phase 2, preCommit: if all votes were yes, the coordinator sends preCommit. Each participant acknowledges and records that the decision is going to be commit. This is the new middle state that 2PC lacks. The key property is that the protocol only reaches preCommit when it already knows no participant voted no, so a commit is now safe.
Phase 3, doCommit: the coordinator sends doCommit and participants finalize and release locks. The recovery rule is what makes 3PC non-blocking: if the coordinator dies, a participant that has reached preCommit can time out and commit anyway, because preCommit guarantees everyone agreed. A participant still in the canCommit state will time out and abort. Either way it acts without waiting forever.
The catch is the assumption behind that recovery rule. 3PC is non-blocking only under a synchronous model with reliable failure detection and no network partitions. In a real asynchronous network a partition can split nodes that timed out and committed from nodes that timed out and aborted, producing an inconsistent result. That is the practical reason it is rarely deployed.