Saturday, August 28, 2010

What Do Shaolin Wear?

Semaphore

Hello as they are, today we see an example of how to use Semaphore in Java, since version 1.5 was made some important extensions to the package which came java.util.concurrent accompanied Semaphore class which provides the functionality you need.

To understand what we use based on a real example in my work a few days ago came the next issue, we have some singleton classes that act as Providers, the problem is that we turn the concurrent use this Provider and each makes a refresh of the data to have the latest version of the data. This week it happened that N processes (will post N = 5) ran about the same time thus each attempt to cool the singleton all at once as the method that makes the refresh is synchronized happened that updated data for 1 and Thread Thread the other 4 waiting, then again to freshen the following Thread and other expected and so on, I attached a picture to better understand the problem.
Problem Image
5 To avoid performing the refresh Thread decided to run just a refresh and glue the other 4 waiting for the refresh being conducted by the finish, this had to change our singleton and use semaphores and syncronized by a mutex . Here is the modified Singleton class and now explain each step.
  
com.javacuriosities.examples package;

import java.util.ArrayList;
import java.util.List;
java.util.concurrent.Semaphore import;

public class Singleton {

private static Singleton instance;

private volatile boolean refreshing = false;

private Object mutex = new Object();

private List<Semaphore> pendings = new ArrayList<Semaphore>();

public synchronized static Singleton getSingleInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

public void refreshAll(String threadName) {
if (!checkRefreshingStatus()) {
refresh(threadName);
} else {
Semaphore markPending = addSemaphore(threadName);
acquireSemaphore(markPending, threadName);
}
}

private void refresh(String threadName) {
try {
refreshInfo(threadName);
} catch (Exception e) {
e.printStackTrace();
} finally {
releasePending();
}
}

private void acquireSemaphore(Semaphore markPending, String threadName) {
try {
if (markPending != null) {
System.out.println("Acquire semaphore: " + threadName);
markPending.acquire();
} else {
System.out.println("Avoid semaphore: " + threadName);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private Semaphore addSemaphore(String threadName) {
Semaphore markPending = null;
synchronized (mutex) {
if (isRefreshing()) {
markPending = new Semaphore(0, true);
pendings.add(markPending);
System.out.println("Add semaphore to: " + threadName);
}
}
return markPending;
}

private void releasePending() {
synchronized (mutex) {
System.out.println("Release semaphores");
for (Semaphore semaphore : pendings) {
semaphore.release(); Pendings.clear

} ();
refreshing = false;

}} private synchronized boolean

checkRefreshingStatus () {boolean
previousState = refreshing;
if (! Refreshing) {
refreshing = true;}
return
previousState ;
} private void

refreshInfo (String threadName)
{for (int i = 0; i < 1000; i++) {
System.out.println ("Executing refresh:" + threadName)

}} public boolean

isRefreshing () {
refreshing return;
}}

I'll explain all the changes we made to get what we expected to turn we will see how serious the flow of execution. Note: The class has been modified to serve for testing and example.
1) The method refreshAll stopped being synchronized.
2) soon begins an IF method which we call a synchronized method that asks if you are cooling and changing the flag state of refreshing.
3) The first Thread coming to this part to enter the IF others will go down the ELSE.
4) The Thread 1 starts to refresh the information, others are on the side and enter ELSE addSemaphore method as we see this method uses mutex synchronization to make sure this is not added to the list semaphores while we are releasing on the other hand, if the list is not being released and it is still running the refresh create a semaphore and returns.
5) If you could create the semaphore is trying to acquire the same, if not manage to create means that the refresh term and was not necessary to wait. We use the method to tell you acquire a semaphore that is waiting until it is released this would be the equivalent of making this.wait () and wait for another part of the code will make a this.notify ().
6) Another important issue is that if the refresh logic fails as we release the semaphores outstanding but we locked the process., So the releasePending is in a finally block.

Note that the semaphore is created with 0 Permits so significant that when you acquire hope that the number of Permits this to 1, this is achieved through the release method that increases by 1 the Permits of the semaphore.

I attached a zip with the singleton class plus a class test that shoots 20 Threads. I hope this post will be helpful to see an example of concurrency and threading in Java, anything that is not understood the post all questions are welcome as well as criticism.

This post is in honor of Tuky that ultimately is very curious about various programming topics. Example



Greetings, Luis

0 comments:

Post a Comment