diff --git a/src/cell.c b/src/cell.c
index c8fb2901cb3a5796ce3bb099955e23bd6520a02d..bfcecc94d95f9247a43e50a3f31031d979668f3b 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -83,7 +83,7 @@ int cell_locktree( struct cell *c ) {
     TIMER_TIC
 
     /* First of all, try to lock this cell. */
-    if ( lock_trylock( &c->lock ) != 0 ) {
+    if ( c->hold || lock_trylock( &c->lock ) != 0 ) {
         TIMER_TOC(cell_timer_tree);
         return 1;
         }
diff --git a/src/queue.c b/src/queue.c
index 79edee4d282af7423c1c03ed4e70adf534de3519..320d604a944002a151cd45fc18ac45d7acc17aa0 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -272,6 +272,7 @@ struct task *queue_gettask ( struct queue *q , int rid , int blocking , int keep
     int k, tid = -1, qcount, *qtid = q->tid;
     lock_type *qlock = &q->lock;
     struct task *qtasks = q->tasks, *res = NULL;
+    struct cell *ci_best = NULL, *cj_best = NULL;
     int ind_best, score_best = -1, score;
     TIMER_TIC
     
@@ -312,34 +313,39 @@ struct task *queue_gettask ( struct queue *q , int rid , int blocking , int keep
                 score = ( res->ci->owner == rid ) + ( res->cj->owner == rid );
             if ( score <= score_best )
                 continue;
-            
-            /* Different criteria for different types. */
+                
+            /* Try to lock ci. */
             if ( res->type == task_type_self || (res->type == task_type_sub && res->cj == NULL) ) {
-                if ( res->ci->hold || cell_locktree( res->ci ) != 0 )
+                if ( res->ci != ci_best && res->ci != cj_best && cell_locktree( res->ci ) != 0 )
                     continue;
                 }
             else if ( res->type == task_type_pair || (res->type == task_type_sub && res->cj != NULL) ) {
                 if ( res->ci->hold || res->cj->hold || res->ci->wait || res->cj->wait )
                     continue;
-                if ( cell_locktree( res->ci ) != 0 )
+                if ( res->ci != ci_best && res->ci != cj_best && cell_locktree( res->ci ) != 0 )
                     continue;
-                if ( cell_locktree( res->cj ) != 0 ) {
-                    cell_unlocktree( res->ci );
+                if ( res->cj != ci_best && res->cj != cj_best && cell_locktree( res->cj ) != 0 ) {
+                    if ( res->ci != ci_best && res->ci != cj_best )
+                        cell_unlocktree( res->ci );
                     continue;
                     }
                 }
-                
+            
             /* If we owned a previous task, unlock it. */
             if ( ind_best >= 0 ) {
                 res = &qtasks[ qtid[ ind_best ] ];
                 if ( res->type == task_type_self || res->type == task_type_pair || res->type == task_type_sub )
-                    cell_unlocktree( res->ci );
+                    if ( res->ci != ci_best && res->ci != cj_best )
+                        cell_unlocktree( res->ci );
                 if ( res->type == task_type_pair || (res->type == task_type_sub && res->cj != NULL) )
-                    cell_unlocktree( res->cj );
+                    if ( res->cj != ci_best && res->cj != cj_best )
+                        cell_unlocktree( res->cj );
                 }
             
             /* If we made it this far, we're safe. */
             ind_best = k;
+            ci_best = qtasks[ qtid[ k ] ].ci;
+            cj_best = qtasks[ qtid[ k ] ].cj;
             score_best = score;
             
             /* Should we bother looking any farther? */