The Yamaha rider started from second place behind title rival Casey Stoner but was pushed hardest for the victory by the Australian's Honda team-mate Dani Pedrosa, who profited from a dream getaway at the start to take a well-earned second place.
With Stoner finishing fourth, Lorenzo extended his lead in the riders' standings to 20 points heading into the British round at Silverstone in a fortnight.
Tech 3 Yamaha's Andrea Dovizioso produced a sterling ride to claim the final podium place a fraction ahead of Stoner, with the Italian's British team-mate Cal Crutchlow having to settle for fifth after starting the race from a career-best third place.
"It was a very tough race. It was hot and very complicated," Lorenzo told BBC Sport.
"I waited my opportunity. With Dani he raced very close and I didn't want to touch him, so I waited for one mistake from him to take my opportunity."
Pole-sitter Stoner, Lorenzo and Crutchlow failed to make their most of their front-row berths at the start as Pedrosa and the second factory Yamaha of Ben Spies blasted through to lead the pack into turn one.
Spies, who is under pressure to turn in better performances at Yamaha, attempted to take the lead on lap three but ran wide and ended on his side in the gravel.
The American mounted a solid recovery ride to take 10th at the flag, although a podium was surely there for the taking had he made the pass stick.
The race instead came down to a straight duel between Pedrosa and Lorenzo, the two Spaniards putting on a great show for their fans at the Barcelona circuit.
Lorenzo got the run on Pedrosa to take the lead on the entry to the first turn on lap seven but the Honda man was able to hit the front again with 14 laps remaining.
Lorenzo ran wide to allow Dovizioso to briefly threaten his hold on second, but the 2010 champion pulled clear of the Italian and with six laps to go passed Pedrosa to take the lead for good and his third win in five races this season.
Watch: Lorenzo takes thrilling Catalunya win... More Videos
Pedrosa, who now trails Lorenzo by 30 points in the standings, admitted his frustration at failing to register his first win of the campaign.
"I had some issues at the end. I wanted to be faster and I expected to be better," he told BBC Sport.
"I did my best in the middle of the race, tried to attack, came back strong because he pushed me wide in the first turn.
"I'm a little bit disappointed. I wanted to win pretty bad."
Alvaro Bautista (Honda Gresini) took sixth place ahead of the Ducati of Valentino Rossi, the LCR Honda of Stefan Bradl and the second Ducati of Nicky Hayden.