code: public void updateJobStatus(final JobIdentifier jobIdentifier, final JobState jobState) throws Exception {
          // have to synchronize at stage-level because cancellation happens at stage-level
          final String stageMutex = mutexForStageInstance(jobIdentifier);
          synchronized (stageMutex) {
              synchronized (mutexForJob(jobIdentifier)) {
                  final JobInstance job = jobInstanceService.buildByIdWithTransitions(jobIdentifier.getBuildId());
  
                  transactionTemplate.executeWithExceptionHandling(new com.thoughtworks.go.server.transaction.TransactionCallbackWithoutResult() {
                      public void doInTransactionWithoutResult(TransactionStatus status) {
                          if (job.isNull() || job.getState() == JobState.Rescheduled || job.getResult() == JobResult.Cancelled) {
                              return;
                          }
  
                          job.changeState(jobState);
                          //TODO: #2318 JobInstance should contain identifier after it's loaded from database
                          job.setIdentifier(jobIdentifier);
                          jobInstanceService.updateStateAndResult(job);
  
                          synchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                              @Override
                              public void afterCommit() {
                                  stageDao.clearCachedAllStages(jobIdentifier.getPipelineName(), jobIdentifier.getPipelineCounter(), jobIdentifier.getStageName());
                              }
                          });
  
                          if (job.isCompleted()) {
                              Stage stage = stageService.stageById(job.getStageId());
                              stageService.updateResult(stage);
                          }
                      }
                  });
  
                  // this has to be in a separate transaction because the above should not fail due to errors when scheduling a the next stage
                  // (e.g. CannotScheduleException thrown when there are no agents for run-on-all-agent jobs)
                  transactionTemplate.executeWithExceptionHandling(new com.thoughtworks.go.server.transaction.TransactionCallbackWithoutResult() {
                      @Override
                      public void doInTransactionWithoutResult(TransactionStatus status) throws Exception {
                          if (job.isCompleted()) {
                              Stage stage = stageService.stageById(job.getStageId());
                              automaticallyTriggerRelevantStagesFollowingCompletionOf(stage);
                          }
                      }
                  });
              }
          }
      }
docs: synchronized for updating job