diff --git a/src/main/java/org/jboss/ejb/client/remoting/ConnectionPool.java b/src/main/java/org/jboss/ejb/client/remoting/ConnectionPool.java
index d59c4a1..dbbf165 100644
--- a/src/main/java/org/jboss/ejb/client/remoting/ConnectionPool.java
+++ b/src/main/java/org/jboss/ejb/client/remoting/ConnectionPool.java
@@ -27,6 +27,7 @@ import java.io.IOException;
 import java.security.Principal;
 import java.util.Collection;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
@@ -64,52 +65,79 @@ class ConnectionPool {
 
     private final ConcurrentMap<CacheKey, PooledConnection> cache = new ConcurrentHashMap<CacheKey, PooledConnection>();
 
+    private final ConcurrentMap<MutexKey, Object> mutexMap = new ConcurrentHashMap<MutexKey, Object>();
+
     private ConnectionPool() {
 
     }
 
-    synchronized Connection getConnection(final Endpoint clientEndpoint, final String protocol, final String host, final int port, final EJBClientConfiguration.CommonConnectionCreationConfiguration connectionConfiguration) throws IOException {
-        final CacheKey key = new CacheKey(clientEndpoint, connectionConfiguration.getCallbackHandler(), connectionConfiguration.getConnectionCreationOptions(), host, port, protocol);
-        PooledConnection pooledConnection = cache.get(key);
-        if (pooledConnection == null) {
-            final IoFuture<Connection> futureConnection = NetworkUtil.connect(clientEndpoint, protocol, host, port, null, connectionConfiguration.getConnectionCreationOptions(), connectionConfiguration.getCallbackHandler(), null);
-            // wait for the connection to be established
-            final Connection connection = IoFutureHelper.get(futureConnection, connectionConfiguration.getConnectionTimeout(), TimeUnit.MILLISECONDS);
-            // We don't want to hold stale connection(s), so add a close handler which removes the entry
-            // from the cache when the connection is closed
-            connection.addCloseHandler(new CacheEntryRemovalHandler(key));
-
-            pooledConnection = new PooledConnection(key, connection);
-            // add it to the cache
-            cache.put(key, pooledConnection);
+    //Kyriba-made change at 17.02.2015: avoid synchronization on ConnectionPool instance to prevent situation
+    //when a connection to one unavailable server has impact to all the others
+    Connection getConnection(final Endpoint clientEndpoint, final String protocol, final String host, final int port, final EJBClientConfiguration.CommonConnectionCreationConfiguration connectionConfiguration) throws IOException {
+        CallbackHandler connectionHandler = connectionConfiguration.getCallbackHandler();
+        OptionMap connectionCreationOptions = connectionConfiguration.getConnectionCreationOptions();
+        synchronized (getMutex(connectionHandler, connectionCreationOptions)) {
+            final CacheKey key = new CacheKey(clientEndpoint, connectionConfiguration.getCallbackHandler(), connectionConfiguration.getConnectionCreationOptions(), host, port, protocol);
+            PooledConnection pooledConnection = cache.get(key);
+            if (pooledConnection == null) {
+                final IoFuture<Connection> futureConnection = NetworkUtil.connect(clientEndpoint, protocol, host, port, null, connectionConfiguration.getConnectionCreationOptions(), connectionConfiguration.getCallbackHandler(), null);
+                // wait for the connection to be established
+                final Connection connection;
+                try {
+                    connection = IoFutureHelper.get(futureConnection, connectionConfiguration.getConnectionTimeout(), TimeUnit.MILLISECONDS);
+                }
+                catch (RuntimeException e) {
+                    //Kyriba-made change at 17.02.2015: avoid the situation when there is no response to connection establishment
+                    //request and as a result notifier's methods are not invoked. such situation leads to deadlock at the time
+                    //org.jboss.remoting3.EndpointImpl try to close itself
+                    if (e.getMessage() != null && e.getMessage().contains("Operation failed with status WAITING"))
+                        futureConnection.cancel();
+
+                    throw e;
+                }
+                // We don't want to hold stale connection(s), so add a close handler which removes the entry
+                // from the cache when the connection is closed
+                connection.addCloseHandler(new CacheEntryRemovalHandler(key));
+
+                pooledConnection = new PooledConnection(key, connection);
+                // add it to the cache
+                cache.put(key, pooledConnection);
+            }
+            pooledConnection.referenceCount.incrementAndGet();
+            return pooledConnection;
         }
-        pooledConnection.referenceCount.incrementAndGet();
-        return pooledConnection;
     }
 
-    synchronized void release(final CacheKey connectionHash, final boolean async) {
-        final PooledConnection pooledConnection = cache.get(connectionHash);
-        if (pooledConnection == null) {
-            return;
-        }
-        if (pooledConnection.referenceCount.decrementAndGet() == 0) {
-            try {
-                final Connection connection = pooledConnection.underlyingConnection;
-                if (async) {
-                    connection.closeAsync();
-                } else {
-                    safeClose(connection);
+    void release(final CacheKey connectionHash, final boolean async) {
+        synchronized (getMutex(connectionHash.callbackHandler, connectionHash.connectOptions)) {
+            final PooledConnection pooledConnection = cache.get(connectionHash);
+            if (pooledConnection == null) {
+                return;
+            }
+            if (pooledConnection.referenceCount.decrementAndGet() == 0) {
+                try {
+                    final Connection connection = pooledConnection.underlyingConnection;
+                    if (async) {
+                        connection.closeAsync();
+                    }
+                    else {
+                        safeClose(connection);
+                    }
+                }
+                finally {
+                    cache.remove(connectionHash);
                 }
-            } finally {
-                cache.remove(connectionHash);
             }
         }
     }
 
-    private synchronized void shutdown() {
+    private void shutdown() {
         for (Map.Entry<CacheKey, PooledConnection> entry : cache.entrySet()) {
-            final Connection connection = entry.getValue().underlyingConnection;
-            safeClose(connection);
+            CacheKey key = entry.getKey();
+            synchronized (getMutex(key.callbackHandler, key.connectOptions)) {
+                final Connection connection = entry.getValue().underlyingConnection;
+                safeClose(connection);
+            }
         }
         cache.clear();
     }
@@ -279,4 +307,50 @@ class ConnectionPool {
         }
     }
 
+
+    private static final class MutexKey {
+        private final CallbackHandler callbackHandler;
+        private final OptionMap connectionCreationOptions;
+        private final int hashCode;
+
+        private MutexKey(CallbackHandler callbackHandler, OptionMap connectionCreationOptions) {
+            this.callbackHandler = callbackHandler;
+            this.connectionCreationOptions = connectionCreationOptions;
+            hashCode = initHashCode();
+        }
+
+
+        private int initHashCode() {
+            return Objects.hash(connectionCreationOptions, callbackHandler);
+        }
+
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof MutexKey)) return false;
+
+            MutexKey mutexKey = (MutexKey) o;
+
+            return Objects.equals(callbackHandler, mutexKey.callbackHandler)
+                && Objects.equals(connectionCreationOptions, mutexKey.connectionCreationOptions);
+        }
+
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
+
+
+    private Object getMutex(CallbackHandler callbackHandler, OptionMap connectionCreationOptions) {
+        MutexKey mutexKey = new MutexKey(callbackHandler, connectionCreationOptions);
+        Object mutex = mutexMap.get(mutexKey);
+        if (mutex == null) {
+            mutexMap.putIfAbsent(mutexKey, new Object());
+            mutex = mutexMap.get(mutexKey);
+        }
+        return mutex;
+    }
 }
