diff --git a/h2/src/main/org/h2/table/RegularTable.java b/h2/src/main/org/h2/table/RegularTable.java
index f607396..ffec091 100644
--- a/h2/src/main/org/h2/table/RegularTable.java
+++ b/h2/src/main/org/h2/table/RegularTable.java
@@ -534,39 +534,41 @@ private void doLock1(Session session, int lockMode, boolean exclusive) {
     }
 
     private boolean doLock2(Session session, int lockMode, boolean exclusive) {
-        if (exclusive) {
-            if (lockExclusiveSession == null) {
-                if (lockSharedSessions.isEmpty()) {
-                    traceLock(session, exclusive, "added for");
-                    session.addLock(this);
-                    lockExclusiveSession = session;
-                    return true;
-                } else if (lockSharedSessions.size() == 1 &&
-                        lockSharedSessions.contains(session)) {
-                    traceLock(session, exclusive, "add (upgraded) for ");
-                    lockExclusiveSession = session;
-                    return true;
-                }
-            }
-        } else {
-            if (lockExclusiveSession == null) {
-                if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
-                    if (!database.isMultiThreaded() && !database.isMultiVersion()) {
-                        // READ_COMMITTED: a read lock is acquired,
-                        // but released immediately after the operation
-                        // is complete.
-                        // When allowing only one thread, no lock is
-                        // required.
-                        // Row level locks work like read committed.
+        synchronized (this) {
+            if (exclusive) {
+                if (lockExclusiveSession == null) {
+                    if (lockSharedSessions.isEmpty()) {
+                        traceLock(session, exclusive, "added for");
+                        session.addLock(this);
+                        lockExclusiveSession = session;
+                        return true;
+                    } else if (lockSharedSessions.size() == 1 &&
+                            lockSharedSessions.contains(session)) {
+                        traceLock(session, exclusive, "add (upgraded) for ");
+                        lockExclusiveSession = session;
                         return true;
                     }
                 }
-                if (!lockSharedSessions.contains(session)) {
-                    traceLock(session, exclusive, "ok");
-                    session.addLock(this);
-                    lockSharedSessions.add(session);
+            } else {
+                if (lockExclusiveSession == null) {
+                    if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
+                        if (!database.isMultiThreaded() && !database.isMultiVersion()) {
+                            // READ_COMMITTED: a read lock is acquired,
+                            // but released immediately after the operation
+                            // is complete.
+                            // When allowing only one thread, no lock is
+                            // required.
+                            // Row level locks work like read committed.
+                            return true;
+                        }
+                    }
+                    if (!lockSharedSessions.contains(session)) {
+                        traceLock(session, exclusive, "ok");
+                        session.addLock(this);
+                        lockSharedSessions.add(session);
+                    }
+                    return true;
                 }
-                return true;
             }
         }
         return false;
@@ -639,12 +641,15 @@ private static String getDeadlockDetails(ArrayList<Session> sessions, boolean ex
                     }
                 }
             }
-            if (error == null && lockExclusiveSession != null) {
-                Table t = lockExclusiveSession.getWaitForLock();
-                if (t != null) {
-                    error = t.checkDeadlock(lockExclusiveSession, clash, visited);
-                    if (error != null) {
-                        error.add(session);
+            synchronized (this)
+            {
+                if (error == null && lockExclusiveSession != null) {
+                    Table t = lockExclusiveSession.getWaitForLock();
+                    if (t != null) {
+                        error = t.checkDeadlock(lockExclusiveSession, clash, visited);
+                        if (error != null) {
+                            error.add(session);
+                        }
                     }
                 }
             }
@@ -667,14 +672,16 @@ public boolean isLockedExclusively() {
     @Override
     public void unlock(Session s) {
         if (database != null) {
-            traceLock(s, lockExclusiveSession == s, "unlock");
-            if (lockExclusiveSession == s) {
-                lockExclusiveSession = null;
-            }
-            synchronized (database) {
+            synchronized (this) {
+                traceLock(s, lockExclusiveSession == s, "unlock");
+                if (lockExclusiveSession == s) {
+                    lockExclusiveSession = null;
+                }
                 if (!lockSharedSessions.isEmpty()) {
                     lockSharedSessions.remove(s);
                 }
+            }
+            synchronized (database) {
                 if (!waitingSessions.isEmpty()) {
                     database.notifyAll();
                 }
@@ -720,7 +727,10 @@ public void removeChildrenAndResources(Session session) {
         scanIndex.remove(session);
         database.removeMeta(session, getId());
         scanIndex = null;
-        lockExclusiveSession = null;
+        synchronized (this)
+        {
+            lockExclusiveSession = null;
+        }
         lockSharedSessions = null;
         invalidate();
     }
