Every core keeps a private cache, so hardware runs a coherence protocol to keep their copies honest. Under MESI, each cache line is in one of four states — Modified, Exclusive, Shared, or Invalid. Reads may share a line freely, but a write demands exclusive ownership: it broadcasts an invalidate on the bus, knocking every other core's copy to Invalid.
Coherence works on whole 64-byte lines, not on variables. So if core 0's counter and core 1's counter happen to land on the same line, each write to one invalidates the other's copy — even though the two counters never share a single byte of data. The cores ping-pong the line's ownership back and forth on every write: the bus drowns in invalidation traffic and both cores stall. This is false sharing.
It is the canonical performance bug you cannot see in the source code — the two lines look completely independent. The fix costs nothing: pad or reorder the layout so the hot variables sit on different lines. Slide one counter 64 bytes over and the storm goes silent. A read-mostly value kept on its own line simply stays Shared in both caches, and the bus never has to say another word about it.
The simulation stopped unexpectedly — the lesson continues without it. You can move on; nothing you did was wrong.