8196787: (ch) Moving network channels to use j.u.c locks
authoralanb
Tue, 06 Feb 2018 16:04:46 +0000
changeset 48750 ffbb784a8873
parent 48749 fd40b0b3d849
child 48751 54f355e65415
8196787: (ch) Moving network channels to use j.u.c locks Reviewed-by: prappo, rriggs
src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
src/java.base/share/classes/sun/nio/ch/IOUtil.java
src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java
src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java
src/java.base/unix/native/libnio/ch/SocketChannelImpl.c
src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java
src/java.base/windows/classes/sun/nio/ch/SourceChannelImpl.java
src/java.base/windows/native/libnio/ch/SocketChannelImpl.c
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,32 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.net.*;
+import java.net.DatagramSocket;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.PortUnreachableException;
+import java.net.ProtocolFamily;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardProtocolFamily;
+import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
+import java.nio.channels.AlreadyBoundException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.MembershipKey;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
 import sun.net.ResourceManager;
 import sun.net.ext.ExtendedSocketOptions;
 
@@ -67,10 +88,10 @@
     private int cachedSenderPort;
 
     // Lock held by current reading or connecting thread
-    private final Object readLock = new Object();
+    private final ReentrantLock readLock = new ReentrantLock();
 
     // Lock held by current writing or connecting thread
-    private final Object writeLock = new Object();
+    private final ReentrantLock writeLock = new ReentrantLock();
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
@@ -328,7 +349,8 @@
     public SocketAddress receive(ByteBuffer dst) throws IOException {
         if (dst.isReadOnly())
             throw new IllegalArgumentException("Read-only buffer");
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             ensureOpen();
             // Socket was not bound before attempting receive
             if (localAddress() == null)
@@ -348,6 +370,8 @@
                     if (n == IOStatus.UNAVAILABLE)
                         return null;
                 } else {
+                    // Cannot receive into user's buffer when running with a
+                    // security manager and not connected
                     bb = Util.getTemporaryDirectBuffer(dst.remaining());
                     for (;;) {
                         do {
@@ -379,6 +403,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -425,7 +451,8 @@
         if (src == null)
             throw new NullPointerException();
 
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             ensureOpen();
             InetSocketAddress isa = Net.checkAddress(target);
             InetAddress ia = isa.getAddress();
@@ -474,6 +501,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -534,7 +563,8 @@
     public int read(ByteBuffer buf) throws IOException {
         if (buf == null)
             throw new NullPointerException();
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             synchronized (stateLock) {
                 ensureOpen();
                 if (!isConnected())
@@ -555,6 +585,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -563,7 +595,8 @@
     {
         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
             throw new IndexOutOfBoundsException();
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             synchronized (stateLock) {
                 ensureOpen();
                 if (!isConnected())
@@ -584,13 +617,16 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
     public int write(ByteBuffer buf) throws IOException {
         if (buf == null)
             throw new NullPointerException();
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             synchronized (stateLock) {
                 ensureOpen();
                 if (!isConnected())
@@ -611,6 +647,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -619,7 +657,8 @@
     {
         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
             throw new IndexOutOfBoundsException();
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             synchronized (stateLock) {
                 ensureOpen();
                 if (!isConnected())
@@ -640,6 +679,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -661,8 +702,10 @@
 
     @Override
     public DatagramChannel bind(SocketAddress local) throws IOException {
-        synchronized (readLock) {
-            synchronized (writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 synchronized (stateLock) {
                     ensureOpen();
                     if (localAddress != null)
@@ -692,7 +735,11 @@
                     Net.bind(family, fd, isa.getAddress(), isa.getPort());
                     localAddress = Net.localAddress(fd);
                 }
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
         return this;
     }
@@ -714,8 +761,10 @@
 
     @Override
     public DatagramChannel connect(SocketAddress sa) throws IOException {
-        synchronized(readLock) {
-            synchronized(writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 synchronized (stateLock) {
                     ensureOpenAndUnconnected();
                     InetSocketAddress isa = Net.checkAddress(sa);
@@ -759,14 +808,20 @@
                         }
                     }
                 }
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
         return this;
     }
 
     public DatagramChannel disconnect() throws IOException {
-        synchronized(readLock) {
-            synchronized(writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 synchronized (stateLock) {
                     if (!isConnected() || !isOpen())
                         return this;
@@ -783,7 +838,11 @@
                     // refresh local address
                     localAddress = Net.localAddress(fd);
                 }
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
         return this;
     }
@@ -1087,7 +1146,8 @@
     int poll(int events, long timeout) throws IOException {
         assert Thread.holdsLock(blockingLock()) && !isBlocking();
 
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             int n = 0;
             try {
                 begin();
@@ -1102,6 +1162,8 @@
                 end(n > 0);
             }
             return n;
+        } finally {
+            readLock.unlock();
         }
     }
 
--- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@
             src.position(pos);
 
             int n = writeFromNativeBuffer(fd, bb, position,
-                    directIO, alignment, nd);
+                                          directIO, alignment, nd);
             if (n > 0) {
                 // now update src
                 src.position(pos + n);
@@ -161,8 +161,7 @@
                     if (!(buf instanceof DirectBuffer)) {
                         ByteBuffer shadow;
                         if (directIO)
-                            shadow = Util.getTemporaryAlignedDirectBuffer(rem,
-                                    alignment);
+                            shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
                         else
                             shadow = Util.getTemporaryDirectBuffer(rem);
                         shadow.put(buf);
@@ -241,8 +240,7 @@
         int rem = dst.remaining();
         if (directIO) {
             Util.checkRemainingBufferSizeAligned(rem, alignment);
-            bb = Util.getTemporaryAlignedDirectBuffer(rem,
-                                                      alignment);
+            bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
         } else {
             bb = Util.getTemporaryDirectBuffer(rem);
         }
@@ -277,8 +275,7 @@
             return 0;
         int n = 0;
         if (position != -1) {
-            n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
-                         rem, position);
+            n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, rem, position);
         } else {
             n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
         }
@@ -332,8 +329,7 @@
                     if (!(buf instanceof DirectBuffer)) {
                         ByteBuffer shadow;
                         if (directIO) {
-                            shadow = Util.getTemporaryAlignedDirectBuffer(rem,
-                                    alignment);
+                            shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
                         } else {
                             shadow = Util.getTemporaryDirectBuffer(rem);
                         }
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,25 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.net.*;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardProtocolFamily;
+import java.net.StandardSocketOptions;
+import java.nio.channels.AlreadyBoundException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
 import sun.net.NetHooks;
 
 /**
@@ -56,7 +71,7 @@
     private volatile long thread;
 
     // Lock held by thread currently blocked in this channel
-    private final Object lock = new Object();
+    private final ReentrantLock acceptLock = new ReentrantLock();
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
@@ -77,7 +92,7 @@
     private boolean isReuseAddress;
 
     // Our socket adaptor, if any
-    ServerSocket socket;
+    private ServerSocket socket;
 
     // -- End of fields protected by stateLock
 
@@ -211,7 +226,8 @@
 
     @Override
     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
-        synchronized (lock) {
+        acceptLock.lock();
+        try {
             if (!isOpen())
                 throw new ClosedChannelException();
             if (isBound())
@@ -227,12 +243,15 @@
             synchronized (stateLock) {
                 localAddress = Net.localAddress(fd);
             }
+        } finally {
+            acceptLock.unlock();
         }
         return this;
     }
 
     public SocketChannel accept() throws IOException {
-        synchronized (lock) {
+        acceptLock.lock();
+        try {
             if (!isOpen())
                 throw new ClosedChannelException();
             if (!isBound())
@@ -278,6 +297,8 @@
             }
             return sc;
 
+        } finally {
+            acceptLock.unlock();
         }
     }
 
@@ -353,7 +374,8 @@
     int poll(int events, long timeout) throws IOException {
         assert Thread.holdsLock(blockingLock()) && !isBlocking();
 
-        synchronized (lock) {
+        acceptLock.lock();
+        try {
             int n = 0;
             try {
                 begin();
@@ -368,6 +390,8 @@
                 end(n > 0);
             }
             return n;
+        } finally {
+            acceptLock.unlock();
         }
     }
 
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,30 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.net.StandardProtocolFamily;
+import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
+import java.nio.channels.AlreadyBoundException;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
 import sun.net.NetHooks;
 import sun.net.ext.ExtendedSocketOptions;
 
@@ -59,10 +78,10 @@
     private volatile long writerThread;
 
     // Lock held by current reading or connecting thread
-    private final Object readLock = new Object();
+    private final ReentrantLock readLock = new ReentrantLock();
 
     // Lock held by current writing or connecting thread
-    private final Object writeLock = new Object();
+    private final ReentrantLock writeLock = new ReentrantLock();
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
@@ -89,7 +108,6 @@
     // Input/Output open
     private boolean isInputOpen = true;
     private boolean isOutputOpen = true;
-    private boolean readyToConnect = false;
 
     // Socket adaptor, created on demand
     private Socket socket;
@@ -298,7 +316,8 @@
         if (buf == null)
             throw new NullPointerException();
 
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             if (!ensureReadOpen())
                 return -1;
             int n = 0;
@@ -418,6 +437,8 @@
                 assert IOStatus.check(n);
 
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -426,7 +447,8 @@
     {
         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
             throw new IndexOutOfBoundsException();
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             if (!ensureReadOpen())
                 return -1;
             long n = 0;
@@ -453,13 +475,16 @@
                 }
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
     public int write(ByteBuffer buf) throws IOException {
         if (buf == null)
             throw new NullPointerException();
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             ensureWriteOpen();
             int n = 0;
             try {
@@ -484,6 +509,8 @@
                 }
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -492,7 +519,8 @@
     {
         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
             throw new IndexOutOfBoundsException();
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             ensureWriteOpen();
             long n = 0;
             try {
@@ -517,12 +545,15 @@
                 }
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
     // package-private
     int sendOutOfBandData(byte b) throws IOException {
-        synchronized (writeLock) {
+        writeLock.lock();
+        try {
             ensureWriteOpen();
             int n = 0;
             try {
@@ -547,6 +578,8 @@
                 }
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -568,8 +601,10 @@
 
     @Override
     public SocketChannel bind(SocketAddress local) throws IOException {
-        synchronized (readLock) {
-            synchronized (writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 synchronized (stateLock) {
                     if (!isOpen())
                         throw new ClosedChannelException();
@@ -587,7 +622,11 @@
                     Net.bind(fd, isa.getAddress(), isa.getPort());
                     localAddress = Net.localAddress(fd);
                 }
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
         return this;
     }
@@ -616,14 +655,16 @@
     }
 
     public boolean connect(SocketAddress sa) throws IOException {
-        synchronized (readLock) {
-            synchronized (writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 ensureOpenAndUnconnected();
                 InetSocketAddress isa = Net.checkAddress(sa);
                 SecurityManager sm = System.getSecurityManager();
                 if (sm != null)
                     sm.checkConnect(isa.getAddress().getHostAddress(),
-                                    isa.getPort());
+                            isa.getPort());
                 synchronized (blockingLock()) {
                     int n = 0;
                     try {
@@ -636,8 +677,8 @@
                                 // notify hook only if unbound
                                 if (localAddress == null) {
                                     NetHooks.beforeTcpConnect(fd,
-                                                           isa.getAddress(),
-                                                           isa.getPort());
+                                            isa.getAddress(),
+                                            isa.getPort());
                                 }
                                 readerThread = NativeThread.current();
                             }
@@ -646,10 +687,9 @@
                                 if (ia.isAnyLocalAddress())
                                     ia = InetAddress.getLocalHost();
                                 n = Net.connect(fd,
-                                                ia,
-                                                isa.getPort());
-                                if (  (n == IOStatus.INTERRUPTED)
-                                      && isOpen())
+                                        ia,
+                                        isa.getPort());
+                                if ((n == IOStatus.INTERRUPTED) && isOpen())
                                     continue;
                                 break;
                             }
@@ -686,13 +726,19 @@
                     }
                 }
                 return false;
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
     public boolean finishConnect() throws IOException {
-        synchronized (readLock) {
-            synchronized (writeLock) {
+        readLock.lock();
+        try {
+            writeLock.lock();
+            try {
                 synchronized (stateLock) {
                     if (!isOpen())
                         throw new ClosedChannelException();
@@ -714,24 +760,20 @@
                             }
                             if (!isBlocking()) {
                                 for (;;) {
-                                    n = checkConnect(fd, false,
-                                                     readyToConnect);
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
+                                    n = checkConnect(fd, false);
+                                    if ((n == IOStatus.INTERRUPTED) && isOpen())
                                         continue;
                                     break;
                                 }
                             } else {
                                 for (;;) {
-                                    n = checkConnect(fd, true,
-                                                     readyToConnect);
+                                    n = checkConnect(fd, true);
                                     if (n == 0) {
                                         // Loop in case of
                                         // spurious notifications
                                         continue;
                                     }
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
+                                    if ((n == IOStatus.INTERRUPTED) && isOpen())
                                         continue;
                                     break;
                                 }
@@ -769,7 +811,11 @@
                     return true;
                 }
                 return false;
+            } finally {
+                writeLock.unlock();
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -903,9 +949,6 @@
         if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
-            // No need to poll again in checkConnect,
-            // the error will be detected there
-            readyToConnect = true;
             return (newOps & ~oldOps) != 0;
         }
 
@@ -918,7 +961,6 @@
             ((intOps & SelectionKey.OP_CONNECT) != 0) &&
             ((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
             newOps |= SelectionKey.OP_CONNECT;
-            readyToConnect = true;
         }
 
         if (((ops & Net.POLLOUT) != 0) &&
@@ -942,7 +984,8 @@
     int poll(int events, long timeout) throws IOException {
         assert Thread.holdsLock(blockingLock()) && !isBlocking();
 
-        synchronized (readLock) {
+        readLock.lock();
+        try {
             int n = 0;
             try {
                 begin();
@@ -957,6 +1000,8 @@
                 end(n > 0);
             }
             return n;
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -1024,8 +1069,7 @@
 
     // -- Native methods --
 
-    private static native int checkConnect(FileDescriptor fd,
-                                           boolean block, boolean ready)
+    private static native int checkConnect(FileDescriptor fd, boolean block)
         throws IOException;
 
     private static native int sendOutOfBandData(FileDescriptor fd, byte data)
--- a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,14 @@
 
 package sun.nio.ch;
 
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.locks.ReentrantLock;
 
 
 class SinkChannelImpl
@@ -40,17 +44,17 @@
     private static final NativeDispatcher nd = new FileDispatcherImpl();
 
     // The file descriptor associated with this channel
-    FileDescriptor fd;
+    private final FileDescriptor fd;
 
     // fd value needed for dev/poll. This value will remain valid
     // even after the value in the file descriptor object has been set to -1
-    int fdVal;
+    private final int fdVal;
 
     // ID of native thread doing write, for signalling
     private volatile long thread;
 
-    // Lock held by current reading thread
-    private final Object lock = new Object();
+    // Lock held by current writing thread
+    private final ReentrantLock writeLock = new ReentrantLock();
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
@@ -155,8 +159,9 @@
     }
 
     public int write(ByteBuffer src) throws IOException {
-        ensureOpen();
-        synchronized (lock) {
+        writeLock.lock();
+        try {
+            ensureOpen();
             int n = 0;
             try {
                 begin();
@@ -172,14 +177,18 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
     public long write(ByteBuffer[] srcs) throws IOException {
         if (srcs == null)
             throw new NullPointerException();
-        ensureOpen();
-        synchronized (lock) {
+
+        writeLock.lock();
+        try {
+            ensureOpen();
             long n = 0;
             try {
                 begin();
@@ -195,6 +204,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            writeLock.unlock();
         }
     }
 
--- a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,14 @@
 
 package sun.nio.ch;
 
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.locks.ReentrantLock;
 
 
 class SourceChannelImpl
@@ -40,17 +44,17 @@
     private static final NativeDispatcher nd = new FileDispatcherImpl();
 
     // The file descriptor associated with this channel
-    FileDescriptor fd;
+    private final FileDescriptor fd;
 
     // fd value needed for dev/poll. This value will remain valid
     // even after the value in the file descriptor object has been set to -1
-    int fdVal;
+    private final int fdVal;
 
     // ID of native thread doing read, for signalling
     private volatile long thread;
 
     // Lock held by current reading thread
-    private final Object lock = new Object();
+    private final ReentrantLock readLock = new ReentrantLock();
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
@@ -155,8 +159,10 @@
     }
 
     public int read(ByteBuffer dst) throws IOException {
-        ensureOpen();
-        synchronized (lock) {
+
+        readLock.lock();
+        try {
+            ensureOpen();
             int n = 0;
             try {
                 begin();
@@ -172,6 +178,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 
@@ -186,8 +194,10 @@
     public long read(ByteBuffer[] dsts) throws IOException {
         if (dsts == null)
             throw new NullPointerException();
-        ensureOpen();
-        synchronized (lock) {
+
+        readLock.lock();
+        try {
+            ensureOpen();
             long n = 0;
             try {
                 begin();
@@ -203,6 +213,8 @@
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 assert IOStatus.check(n);
             }
+        } finally {
+            readLock.unlock();
         }
     }
 }
--- a/src/java.base/unix/native/libnio/ch/SocketChannelImpl.c	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/unix/native/libnio/ch/SocketChannelImpl.c	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,8 +47,7 @@
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
-                                               jobject fdo, jboolean block,
-                                               jboolean ready)
+                                               jobject fdo, jboolean block)
 {
     int error = 0;
     socklen_t n = sizeof(int);
@@ -56,19 +55,16 @@
     int result = 0;
     struct pollfd poller;
 
-    poller.revents = 1;
-    if (!ready) {
-        poller.fd = fd;
-        poller.events = POLLOUT;
-        poller.revents = 0;
-        result = poll(&poller, 1, block ? -1 : 0);
-        if (result < 0) {
-            JNU_ThrowIOExceptionWithLastError(env, "Poll failed");
-            return IOS_THROWN;
-        }
-        if (!block && (result == 0))
-            return IOS_UNAVAILABLE;
+    poller.fd = fd;
+    poller.events = POLLOUT;
+    poller.revents = 0;
+    result = poll(&poller, 1, block ? -1 : 0);
+    if (result < 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "Poll failed");
+        return IOS_THROWN;
     }
+    if (!block && (result == 0))
+       return IOS_UNAVAILABLE;
 
     if (poller.revents) {
         errno = 0;
--- a/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
     implements SelChImpl
 {
     // The SocketChannel assoicated with this pipe
-    SocketChannel sc;
+    final SocketChannel sc;
 
     public FileDescriptor getFD() {
         return ((SocketChannelImpl)sc).getFD();
--- a/src/java.base/windows/classes/sun/nio/ch/SourceChannelImpl.java	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/windows/classes/sun/nio/ch/SourceChannelImpl.java	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
     implements SelChImpl
 {
     // The SocketChannel assoicated with this pipe
-    SocketChannel sc;
+    private final SocketChannel sc;
 
     public FileDescriptor getFD() {
         return ((SocketChannelImpl) sc).getFD();
--- a/src/java.base/windows/native/libnio/ch/SocketChannelImpl.c	Tue Feb 06 23:49:10 2018 +0530
+++ b/src/java.base/windows/native/libnio/ch/SocketChannelImpl.c	Tue Feb 06 16:04:46 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,8 +55,7 @@
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
-                                               jobject fdo, jboolean block,
-                                               jboolean ready)
+                                               jobject fdo, jboolean block)
 {
     int optError = 0;
     int lastError = 0;