Execution cycle of sed s/REGEXP/REPLACEMENT/g

Because with the two ,s in (,\)\(,\), you have already matched the first two ,s and the Regex pattern matched so far won't backtrack for the rest of the line. Only one is left now that is the last , hence it just printed as it is without any * in between it the second last one.

If you have another , in input, you would get the desired (global, g) response:

% echo ,,,, | sed s':\(,\)\(,\):\1*\2:'g
,*,,*,

The why of the question been already answered by @heemayl

Workaround with sed (here assuming GNU sed) - loop recursively as long as a match is found

$ echo ,,, | sed -E ':a s/(,)(,)/\1*\2/ ; ta'
,*,*,

$ echo ,,,, | sed -E ':a s/(,)(,)/\1*\2/ ; ta'
,*,*,*,

POSIXly:

$ echo ,,,, | sed -e :a -e 's/\(,\)\(,\)/\1*\2/; ta'
,*,*,*,

Or with perl

$ echo ,,, | perl -pe 's/,\K(?=,)/*/g'
,*,*,

$ echo ,,,, | perl -pe 's/,\K(?=,)/*/g'
,*,*,*,