Finally not called -> deadlock

No. That is why the recommendation is to avoid using locks in lambdas.

The finally block is also not executed when there is a break or a type exception in a lambda.

finally is pretty much useless in lambdas and therefore using a lock inside a lambda is a really dangerous idea.

I completely agree. Look at the Design Pattern postings. Most of them will provide techniques you can use that should let you avoid the need for lambdas and locks.

Alternatively, you can move to JSR223 Rules and code in Jython, JavaScript, or Groovy. Given that JSR223 Rules and the new Experimental Next-Gen Rules engine both use the same underlying Rules Engine, this would position you fairly well to adopt the NGRE once the Experimental is removed from it’s name.

NOTE: documentation of the NGRE has been started here.

But beware, JSR223 documentation quantity and quality is hit and miss at the moment, but there are efforts starting up to address that as well.

It depends on the specific problem:

Design Pattern Use
Design Pattern: Separation of Behaviors Great for centralizing cross cutting code like sending of alerts. Essentially you are creating Rules that trigger other Rules through an Item.
Design Pattern: Working with Groups in Rules Can be used to combine lots of similar Rules into a single Rule. If you only have one Rule to process all the lights, for example, you don’t need lambdas. Pay particular attention to Member of and triggeringItem which addresses your concern with a “big when”.
Design Pattern: Associated Items Great when used in combination with the previous one, provides a way to access Items that are related to each other making it so you can further consolidate many Rules into one. This addresses much of concern about the “big then”.
Design Pattern: Expire Binding Based Timers Reduces the need for Timers in some cases.

For example, here is my code that sends me an alert when any door is left open for more than an hour.

rule "Keep track of the last time a door was opened or closed"
when
  Member of gDoorSensors changed
then
  if(previousState == NULL) return;

  val name = triggeringItem.name
  val state = triggeringItem.state

  // Double check if the event makes sense with the deadbolt state
  if(name.contains("Front") || name.contains("Back")) {
    val lock = ScriptServiceUtil.getItemRegistry.getItem(name.replace("v", "a") + "_Lock").state
    if(lock == ON) {
      logWarn(logName, name + " appears to be flapping, door changed to " + state + " but deadbolt is locked! Ignoring change.")
      return;
    }
  }

  // Update the time stamp
  postUpdate(name+"_LastUpdate", now.toString)

  // Set the timer if the door is open, cancel if it is closed
  if(state == OPEN) sendCommand(name+"_Timer", "ON")
  else postUpdate(name+"_Timer", "OFF")

  // Set the message
  val msg = new StringBuilder
  msg.append(transform("MAP", "en.map", name) + " was ")
  msg.append(if(state == OPEN) "opened" else "closed")

  var alert = false
  if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
    msg.append(" and it is night")
    alert = true
  }
  if(vPresent.state == OFF) {
    msg.append(" and no one is home")
    alert = true
  }
  msg.append("!")

  // Alert if necessary
  if(alert){
    aAlert.sendCommand(msg.toString)
  }
  // Log the message if we didn't alert
  else {
    logInfo(logName, msg.toString)
  }
end

rule "Timer expired for a door"
when
  Member of gDoorsTimers received command OFF
then
  val doorName = transform("MAP", "en.map", triggeringItem.name)

  aAlert.sendCommand(doorName + " has been open for over an hour")

  if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
        triggeringItem.sendCommand(ON) // reschedule the timer
  }
end

This example uses pretty much all of the mentioned DPs to create Rules that handle any number of door sensors without locks, lambdas, or duplicated code. I’ve only a little bit of code that handles the special case where the door sensor represents one of the doors that has a deadbolt attached to it.

Notice the bulk of the code is building the message to send as an Alert.
Notice how there is nothing that actually directly references specific door sensor Items. I could have 1 door or a dozen doors/windows and use this same single Rule.

NOTE: lock above is Item representing the door deadbolt, not a ReentrantLock.