Synchronizing It is often insecure to synchronize a method performing that performs network transactions can be problematic. Depending on the speed and reliability of the connection, synchronization can stall the program indefinitely causing a huge performance hit. At other times, it can result in temporary or permanent deadlock.
...
This noncompliant code example involves shows the method sendPage()
that sends a Page
object containing information being passed between from a server to a client and a server. The method is synchronized to protect access to so that the array pageBuff
. Calling writeObject()
within the synchronized sendPage
can result in a deadlock condition in high latency networks or when network connections are inherently lossy is accessed safely, when multiple threads request concurrent access.
Code Block | ||
---|---|---|
| ||
// Class Page is defined separately. It stores and returns the Page name via getName() public final boolean SUCCESS = true; public final boolean FAILURE = false; Page[] pageBuff = new Page[MAX_PAGE_SIZE]; public synchronized boolean sendPage(Socket socket, String pageName) throws IOException { // Get the output stream to write the Page to ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); Page targetPage = null; // Find the Page requested by the client (this operation requires synchronization) Page targetPage = null; for(Page p : pageBuff) { if(p.getName().compareTo(pageName) == 0) { targetPage = p; } } // Requested Page requested does not exist if(targetPage == null) { return FAILURE; } // Send the Page to the client (does not require any synchronization) out.writeObject(targetPage); out.flush(); out.close(); return SUCCESS; } |
Calling writeObject()
within the synchronized sendPage()
method can result in delays and deadlock-like conditions in high latency networks or when network connections are inherently lossy.
Compliant Solution
This compliant solution entails separating the actions into a sequence of steps:
...
In this compliant solution, the synchronized method getPage()
is called from an unsynchronized method sendReply()
, to find the appropriate requested Page
requested by the client from the array pageBuff
of type Page
. The in the pageBuff
array. After the Page
is retrieved, the method sendReply()
in turn calls the unsynchronized method sendPage()
to deliver the Page
to the client.
Code Block | ||
---|---|---|
| ||
public boolean sendReply(Socket socket, String pageName) { // No synchronization Page targetPage = getPage(pageName); if(targetPage == null) return FAILURE; return sendPage(socket, targetPage); } private synchronized Page getPage(String pageName) { // Requires synchronization Page targetPage = null; for(Page p : pageBuff) { if(p.getName().equals(pageName)) { targetPage = p; } } return targetPage; } public boolean sendPage(Socket socket, Page page){ try{ // Get the output stream to write the Page to ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); // Send the Page to the client out.writeObject(page); } catch(IOException io){ // If recovery is not possible return FAILURE return FAILURE; } finally { out.flush(); out.close(); } return SUCCESS; } |
...