LOCK IN SHARE MODE permettra au 2ème thread de lire la valeur, mais la valeur réelle sera celle avant la requête (lecture validée) ou avant le démarrage de la transaction (lecture répétable) (puisque MySQL utilise le multi-versioning ; et ce que doivent être vus par la deuxième transaction est défini par le niveau d'isolement). Donc si la 1ère transaction n'est pas validée au moment de la lecture, l'ancienne valeur sera lue.
Dans votre scénario, il est préférable d'avoir 1 transaction qui verrouille l'enregistrement avec select pour la mise à jour, une autre qui fonctionne sur l'enregistrement et sur commit/rollback la troisième déverrouille l'enregistrement.
La deuxième transaction de thread avec select for update attendra la fin de la première, puis lira la valeur réelle et décidera de ne pas continuer avec les autres transactions, mais d'informer l'utilisateur que l'enregistrement est verrouillé.
Pour éviter les blocages, assurez-vous que vous effectuez la select for update
en utilisant un index unique.
Exemple de code :
connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and locked=false);
ps1.executeQuery();
//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true); // here we allow other transactions / threads to see the new value
connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();
// probably more queries
// reset locked to false
PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();
//commit
connection.setautocommit(true);