What I did with my children was to start by teaching them a game we called "stop-go." While holding his/her hand, I'd say GO! and we would walk/run and when I said STOP! we'd stop abruptly and I'd be silly and say "WHOA! That was good stopping!" and make a big deal about it. We'd play this every time we went for a walk until I was sure they understood the concept.
Then I'd allow them to walk next to me and we'd play until they could play the game as well walking beside me.
After that, I'd explain that I will let them run a little ahead if they want to, but if they don't listen, they will have to come back and hold my hand. We'd play again, and that rule would apply without an exception, EVER. We would also practice in the back yard while I sat and they played in the yard.
Yes, there would be tears sometimes with this step, but it was worth it for their safety. Plus, as long as they listened, they were allowed a little more freedom so there was more incentive than just a punishment for not listening.
It takes some time to do all this, but now both my four- and two-year-old are very reliable at responding to the commands STOP and GO. Of course, my two-year-old still needs to be reminded and has to hold my hand when she disobeys, but she JUST turned two, so I don't expect perfection from her yet.
Maybe your son would enjoy learning this way?
Best of luck to you, whatever you decide!
~A.~