diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java
index cab51e8f07461209a7a377a4387f81f869f1d279..68d3f57a2e99340e4b1dbb8c4188a023a8f1aa3d 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java
@@ -20,8 +20,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Semaphore;
 
 import javax.annotation.PostConstruct;
 
@@ -40,6 +38,7 @@ import kieker.webgui.domain.ComponentListContainer;
 import kieker.webgui.domain.DisplayType;
 import kieker.webgui.persistence.IProjectDAO;
 import kieker.webgui.service.IProjectService;
+import kieker.webgui.service.impl.utility.LockManager;
 
 import org.primefaces.model.UploadedFile;
 
@@ -57,8 +56,8 @@ public final class ProjectServiceImpl implements IProjectService {
 
 	private final List<String> projects = Collections.synchronizedList(new ArrayList<String>());
 
-	private final ConcurrentHashMap<String, Semaphore> fileSystemLocks = new ConcurrentHashMap<String, Semaphore>();
-	private final ConcurrentHashMap<String, Semaphore> analysesLocks = new ConcurrentHashMap<String, Semaphore>();
+	private final LockManager fileSystemLockManager = new LockManager();
+	private final LockManager analysesLockManager = new LockManager();
 
 	@Autowired
 	private IProjectDAO projectDAO;
@@ -83,22 +82,21 @@ public final class ProjectServiceImpl implements IProjectService {
 
 	@Override
 	public void addProject(final String projectName, final String username) throws ProjectAlreadyExistingException, IOException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			this.projectDAO.addProject(projectName, username);
 			this.projects.add(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void deleteProject(final String projectName) throws ProjectNotExistingException, IOException, ProjectStillRunningException, LockProjectException {
-		ProjectServiceImpl.tryLockProjects(projectName, this.fileSystemLocks, projectName, this.analysesLocks);
+		this.fileSystemLockManager.lock(projectName);
+		this.analysesLockManager.lock(projectName);
 
-		final Semaphore oldLockObjectA = this.analysesLocks.get(projectName);
-		final Semaphore oldLockObjectB = this.fileSystemLocks.get(projectName);
 		try {
 			final STATE state = this.acManager.getCurrentState(projectName);
 			if ((state == STATE.RUNNING) || (state == STATE.TERMINATING)) {
@@ -106,14 +104,11 @@ public final class ProjectServiceImpl implements IProjectService {
 			}
 			this.projectDAO.removeProject(projectName);
 			this.projects.remove(projectName);
-
-			// Remove the old lock objects
-			this.analysesLocks.remove(projectName);
-			this.fileSystemLocks.remove(projectName);
 		} finally {
-			oldLockObjectA.release();
-			oldLockObjectB.release();
+			this.fileSystemLockManager.unlock(projectName);
+			this.analysesLockManager.unlock(projectName);
 		}
+
 	}
 
 	@Override
@@ -122,14 +117,16 @@ public final class ProjectServiceImpl implements IProjectService {
 		if (originalProjectName.equals(newProjectName)) {
 			throw new ProjectAlreadyExistingException("Source and target are identical");
 		}
-		ProjectServiceImpl.tryLockProjects(originalProjectName, this.fileSystemLocks, newProjectName, this.fileSystemLocks);
+
+		this.fileSystemLockManager.lock(originalProjectName);
+		this.fileSystemLockManager.lock(newProjectName);
 
 		try {
 			this.projectDAO.copyProject(originalProjectName, newProjectName);
 			this.projects.add(newProjectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(originalProjectName, this.fileSystemLocks);
-			ProjectServiceImpl.unlockProject(newProjectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(originalProjectName);
+			this.fileSystemLockManager.unlock(newProjectName);
 		}
 	}
 
@@ -139,7 +136,9 @@ public final class ProjectServiceImpl implements IProjectService {
 		if (originalProjectName.equals(newProjectName)) {
 			throw new ProjectAlreadyExistingException("Source and target are identical");
 		}
-		ProjectServiceImpl.tryLockProjects(originalProjectName, this.fileSystemLocks, newProjectName, this.fileSystemLocks);
+
+		this.fileSystemLockManager.lock(originalProjectName);
+		this.fileSystemLockManager.lock(newProjectName);
 
 		try {
 			this.projectDAO.copyProject(originalProjectName, newProjectName);
@@ -149,111 +148,111 @@ public final class ProjectServiceImpl implements IProjectService {
 				this.projects.remove(originalProjectName);
 			}
 		} finally {
-			ProjectServiceImpl.unlockProject(originalProjectName, this.fileSystemLocks);
-			ProjectServiceImpl.unlockProject(newProjectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(originalProjectName);
+			this.fileSystemLockManager.unlock(newProjectName);
 		}
 	}
 
 	@Override
 	public void importProject(final String projectName, final String username, final UploadedFile file) throws ProjectAlreadyExistingException, IOException,
 			LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			this.projectDAO.importProject(projectName, username, file);
 			this.projects.add(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public MIProject loadProject(final String projectName) throws ProjectNotExistingException, IOException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.loadProject(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public Object loadProject(final String projectName, final ClassContainer classAndMethodContainer) throws ProjectNotExistingException, IOException,
 			LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.loadProject(projectName, classAndMethodContainer);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void saveProject(final String projectName, final MIProject project, final long timeStamp, final boolean overwriteNewerProject, final String username,
 			final String analysisLayout, final String cockpitLayout) throws ProjectNotExistingException, IOException, NewerProjectException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			this.projectDAO.saveProject(projectName, project, timeStamp, overwriteNewerProject, username, analysisLayout, cockpitLayout);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public long getCurrTimeStamp(final String projectName) throws ProjectNotExistingException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getCurrTimeStamp(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void uploadLibrary(final UploadedFile file, final String projectName) throws ProjectNotExistingException, IOException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			this.projectDAO.uploadLibrary(file, projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public ClassLoader getClassLoader(final String projectName, final Object requester) throws ProjectNotExistingException, IOException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getClassLoader(projectName, requester); // NOPMD (ClassLoader)
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public ComponentListContainer getAvailableComponents(final String projectName) throws LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getAvailableComponents(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public List<String> listAllLibraries(final String projectName) throws ProjectNotExistingException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.listAllLibraries(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
@@ -261,157 +260,158 @@ public final class ProjectServiceImpl implements IProjectService {
 	public void initializeAnalysis(final String projectName, final ClassLoader classLoader) throws ProjectNotExistingException, InvalidAnalysisStateException,
 			AnalysisInitializationException, LockProjectException {
 		// We have to lock both - the project and the analysis, as a file has to be loaded
-		ProjectServiceImpl.tryLockProjects(projectName, this.fileSystemLocks, projectName, this.analysesLocks);
+		this.fileSystemLockManager.lock(projectName);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			this.acManager.initializeAnalysis(projectName, classLoader);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void cleanAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			this.acManager.cleanAnalysis(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void startAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			this.acManager.startAnalysis(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void stopAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			this.acManager.stopAnalysis(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public void emergencyShutdownOfAnalysis(final String projectName) throws ProjectNotExistingException, LockProjectException, InvalidAnalysisStateException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			this.acManager.emergencyShutdown(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public Object getDisplay(final String projectName, final String viewName, final String displayName) throws InvalidAnalysisStateException,
 			DisplayNotFoundException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			return this.acManager.getDisplay(projectName, viewName, displayName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public STATE getCurrentState(final String projectName) throws LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			return this.acManager.getCurrentState(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public Object[] getLogEntries(final String projectName) throws InvalidAnalysisStateException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			return this.acManager.getLogEntries(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public boolean deleteLibrary(final String projectName, final String libName) throws IOException, ProjectNotExistingException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.deleteLibrary(projectName, libName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public String getOwner(final String projectName) throws ProjectNotExistingException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getOwner(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public String getLastUser(final String projectName) throws ProjectNotExistingException, LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getLastUser(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public String getAnalysisLayout(final String projectName) throws LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getAnalysisLayout(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public String getCockpitLayout(final String projectName) throws LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.fileSystemLocks);
+		this.fileSystemLockManager.lock(projectName);
 
 		try {
 			return this.projectDAO.getCockpitLayout(projectName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.fileSystemLocks);
+			this.fileSystemLockManager.unlock(projectName);
 		}
 	}
 
 	@Override
 	public DisplayType getDisplayType(final String projectName, final String viewName, final String displayConnectorName) throws LockProjectException {
-		ProjectServiceImpl.tryLockProject(projectName, this.analysesLocks);
+		this.analysesLockManager.lock(projectName);
 
 		try {
 			return this.acManager.getDisplayType(projectName, viewName, displayConnectorName);
 		} finally {
-			ProjectServiceImpl.unlockProject(projectName, this.analysesLocks);
+			this.analysesLockManager.unlock(projectName);
 		}
 	}
 
@@ -422,126 +422,4 @@ public final class ProjectServiceImpl implements IProjectService {
 		}
 	}
 
-	/**
-	 * This method tries to lock the given projects using the given maps. The method makes sure that the projects are locked in a valid order (For this both strings
-	 * are compared. If both are equal, the first map will be used for the first lock).
-	 * 
-	 * @param projectNameA
-	 *            The first project to lock.
-	 * @param lockMapA
-	 *            The map containing the locks.
-	 *            * @param projectNameB
-	 *            The second project to lock.
-	 * @param lockMapB
-	 *            The map containing the locks.
-	 * 
-	 * @throws LockProjectException
-	 *             If the project could not be locked.
-	 */
-	public static void tryLockProjects(final String projectNameA, final ConcurrentHashMap<String, Semaphore> lockMapA, final String projectNameB,
-			final ConcurrentHashMap<String, Semaphore> lockMapB) throws LockProjectException {
-		final String firstProject;
-		final String secondProject;
-		final ConcurrentHashMap<String, Semaphore> firstLockMap;
-		final ConcurrentHashMap<String, Semaphore> secondLockMap;
-
-		// Find the correct order
-		final int compareValue = projectNameA.compareTo(projectNameB);
-		if (compareValue >= 0) {
-			firstProject = projectNameA;
-			secondProject = projectNameB;
-			firstLockMap = lockMapA;
-			secondLockMap = lockMapB;
-		} else {
-			firstProject = projectNameB;
-			secondProject = projectNameA;
-			firstLockMap = lockMapB;
-			secondLockMap = lockMapA;
-		}
-
-		// Now try to lock both projects. If the locking of the second project fails, we have to unlock the first one though
-		ProjectServiceImpl.tryLockProject(firstProject, firstLockMap);
-
-		try {
-			ProjectServiceImpl.tryLockProject(secondProject, secondLockMap);
-		} catch (final LockProjectException ex) {
-			ProjectServiceImpl.unlockProject(firstProject, firstLockMap);
-			throw ex;
-		}
-	}
-
-	/**
-	 * This method tries to lock the given project using the given map.
-	 * 
-	 * @param projectName
-	 *            The project to lock.
-	 * @param lockMap
-	 *            The map containing the locks.
-	 * 
-	 * @throws LockProjectException
-	 *             If the project could not be locked.
-	 */
-	private static void tryLockProject(final String projectName, final ConcurrentHashMap<String, Semaphore> lockMap) throws LockProjectException {
-		// As we also remove locks from time to time, we have to check whether the acquired lock is valid. If we fail to acquire the correct lock too often, the
-		// locking failed.
-		int failCounter = 0;
-
-		while (true) {
-			final Semaphore projectLock = ProjectServiceImpl.getLock(projectName, lockMap);
-			projectLock.acquireUninterruptibly();
-
-			if (lockMap.get(projectName) == projectLock) {
-				// Everything went well
-				return;
-			} else {
-				// The lock is invalid
-				projectLock.release();
-				failCounter++;
-
-				if (failCounter > 10) {
-					// Abort
-					throw new LockProjectException("The project could not be locked.");
-				}
-			}
-		}
-	}
-
-	/**
-	 * Unlocks the given project.
-	 * 
-	 * @param projectName
-	 *            The project to unlock.
-	 * @param lockMap
-	 *            The map containing the locks.
-	 */
-	private static void unlockProject(final String projectName, final ConcurrentHashMap<String, Semaphore> lockMap) {
-		lockMap.get(projectName).release();
-	}
-
-	/**
-	 * This method can be used to get the lock for a given project. If the lock doesn't exist already, a new one will be created.
-	 * 
-	 * @param projectName
-	 *            The project whose lock should be delivered.
-	 * @param lockMap
-	 *            The map containing the locks.
-	 * 
-	 * @return A lock object for the project.
-	 */
-	private static Semaphore getLock(final String projectName, final ConcurrentHashMap<String, Semaphore> lockMap) {
-		// Create a new lock and put it into the map - if it doesn't already contain the key
-		final Semaphore newLock = new Semaphore(1);
-		final Semaphore existLock = lockMap.putIfAbsent(projectName, newLock);
-
-		// Find out which of the both locks is the correct one
-		final Semaphore lock;
-		if (existLock != null) {
-			lock = existLock;
-		} else {
-			lock = newLock;
-		}
-
-		return lock;
-	}
-
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/LockManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/LockManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3180584018e43f2f72a493554e2a4b91505142f
--- /dev/null
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/utility/LockManager.java
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * Copyright 2013 Kieker Project (http://kieker-monitoring.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.webgui.service.impl.utility;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * This manager is responsible for locking critical code using keys. Internally we use {@link ReentrantLock}s, but make sure that they are removed once they are no
+ * longer needed. The manager has been developed with a simple design. If necessary, the manager can be modified in order to provide a faster access to the locks.
+ * 
+ * @author Nils Christian Ehmke
+ */
+public final class LockManager {
+
+	private final Map<String, Lock> locks = new ConcurrentHashMap<String, Lock>();
+
+	/**
+	 * Creates a new instance of this class.
+	 */
+	public LockManager() {
+		// No code necessary
+	}
+
+	/**
+	 * Locks the objects for the given keys in a definite order.
+	 * 
+	 * @param keys
+	 *            The keys used for the locking.
+	 */
+	public void lock(final String[] keys) {
+		// Make sure that the keys are in a definite order
+		Arrays.sort(keys);
+
+		// Lock all keys
+		for (final String key : keys) {
+			this.lock(key);
+		}
+	}
+
+	/**
+	 * Locks the object for the given key.
+	 * 
+	 * @param key
+	 *            The key used for the locking.
+	 */
+	public void lock(final String key) {
+		final Lock lock;
+
+		synchronized (this) {
+			// Get the existing lock object or create it if necessary
+			if (this.locks.containsKey(key)) {
+				lock = this.locks.get(key);
+			} else {
+				lock = new Lock();
+				this.locks.put(key, lock);
+			}
+
+			// Prepare the locking
+			lock.preLock();
+		}
+
+		lock.lock();
+	}
+
+	/**
+	 * Unlocks the object for the given key.
+	 * 
+	 * @param key
+	 *            The key used for the unlocking.
+	 */
+	public void unlock(final String key) {
+		synchronized (this) {
+			// Get the lock object and unlock it
+			final Lock lock = this.locks.get(key);
+			lock.unlock();
+
+			// Remove the lock object if possible
+			if (lock.isFree()) {
+				this.locks.remove(key);
+			}
+		}
+	}
+
+	/**
+	 * This is a helper class containing a lock object and a lock counter.
+	 * 
+	 * @author Nils Christian Ehmke
+	 */
+	private static final class Lock {
+
+		private final ReentrantLock reentrantLock = new ReentrantLock();
+		private final AtomicLong lockCounter = new AtomicLong();
+
+		public Lock() {
+			// No code necessary
+		}
+
+		public boolean isFree() {
+			return this.lockCounter.get() == 0;
+		}
+
+		public void preLock() {
+			this.lockCounter.incrementAndGet();
+		}
+
+		public void lock() {
+			this.reentrantLock.lock();
+		}
+
+		public void unlock() {
+			this.reentrantLock.unlock();
+			this.lockCounter.decrementAndGet();
+		}
+
+	}
+}