Prima di tutto, se posso permettermi, un consiglio generale: se usi funzionalità di MySQL che non sono troppo comuni (come LOCK TABLE e GET_LOCK(), appunto) leggi molto bene la documentazione, per capire come si usano e quali sono le loro limitazioni. In questo caso ti segnalo che GET_LOCK() è abbastanza intelligente, e il tuo IS_FREE_LOCK() introduce un bug; mentre LOCK TABLE non dovrebbe mai (MAI) essere usato con InnoDB. Per il semplice motivo che usano due logiche diverse, e anche se MySQL fa finta di poterle usare insieme, nella realtà penso che non più di 100 persone in tutto il mondo sappiano che cosa succede. E no, non sto esagerando.
La soluzione è semplicissima: usa le transazioni. Avvia la transazione in questo modo:
SET autocommit = 0;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
E alla fine concludi con:
COMMIT;
Al momento in cui leggerai la tabella, MySQL metterà un lock, e nessuno potrà inserire nulla finché non avrai finito. Se invece un altro thread avrà già acquisito un lock di questo tipo, questa transazione resterà in attesa e leggerà il valore massimo solo quando l'altra transazione sarà terminata. Quindi, come vedi, non c'è nessun conflitto.