The problem
Recently I encountered a problem while working with Spring Aspects and a synchronized block of code. After some digging I came to a conclusion: Don't forget to consider the aspects that are applied to a method while working in a multi-threaded environment. Let me explain.
The project I'm working on uses transactional behavior provided by the spring framework. This behavior is applied by AspectJ using the @Transactional annotation at compile time. I have a method that needs to be synchronized, the problem is that there are two beans that inherits from a common base class that implements the synchronized method, so there are two instances that need to be synchronized. The way we solved the problem is by using a synchronized block with an shared lock object. The class structure is show here.
After some time I found that there were some inconsistent data. There problem was that for some reason the code inside the synchronized block appeared to be executed by two different threads at the same time (no way!!!). But as I supposed in the first place it wasn't the case. The real problem was that the method was not "fully" synchronized, I mean, not all the statements in the method were inside the synchronized block. The statements applied by the @Transactional aspect were out of the block, meaning that while one thread could be after the block (i.e. committing the transaction), another thread might already be inside the synchronized block.
Let me build and example (not exactly the same but it shows the problem). Suppose the class, the aspect and the main program.
We may expect the output to be like this (one invocation after the other)
Thread-0 Before perform
Thread-0 Begin method
Thread-0 End method
Thread-0 After perform
Thread-1 Before perform
Thread-1 Begin method
Thread-1 End method
Thread-1 After perform
...
But what really happens is something like this
Thread-0 Before perform
Thread-1 Before perform
Thread-0 Begin method
Thread-0 End method
Thread-1 Begin method
Thread-0 After perform
Thread-0 Before perform
Thread-1 End method
Thread-0 Begin method
Thread-0 End method
Thread-0 After perform
as you can see the execution of the method is synchronized (i.e. only one thread can be executing the block) while the statements in the aspect can be executed by multiple threads at the same time.
The solution
To solve this problem there are two options:
First, synchronize the code which invokes the perform method, as shown here. The problem with this approach is that you need to change every invocation of the method in the client code to include the synchronization block. If you forget to do this you will be in trouble.
Second, create a private method and decorate that one (with the aspect) instead of the public method as show here. As you can see this method allows to solve the problem without changing anything in the client.
A third option can be to refactor the code in a way the synchronization is not necessary, but for now let's keep it this way.
Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts
Wednesday, August 28, 2013
Tuesday, August 4, 2009
Configure Tomcat to work behind a Proxy
Sometimes it's necessary to a Tomcat application to work behind a Proxy server. If this is the case, to get it work it's necessary to tell the virtual machine to "route" all the communications through this proxy server, in order to do that just use the following parameters when the virtual machine is started:
-Dhttp.proxyHost=proxyname -Dhttp.proxyPort=portnumber
And to manage exceptions to proxy connection use:
-Dhttp.noProxyHosts="localhost|127.0.0.1
And finally if the proxy server requires authentication, before any call that use the connection through the proxy call this in your Java code:
Authenticator.setDefault(new SimpleAuthenticator(username,password));
where SimpleAuthenticator is:
-Dhttp.proxyHost=proxyname -Dhttp.proxyPort=portnumber
And to manage exceptions to proxy connection use:
-Dhttp.noProxyHosts="localhost|127.0.0.1
And finally if the proxy server requires authentication, before any call that use the connection through the proxy call this in your Java code:
Authenticator.setDefault(new SimpleAuthenticator(username,password));
where SimpleAuthenticator is:
public class SimpleAuthenticator extends Authenticator {
private String username, password;
public SimpleAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
private String username, password;
public SimpleAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
Saturday, July 25, 2009
Groovy and Java Performance Comparison
First of all, I don't want to get into discussions about the advantages or disadvantages of one or the another. Java is a compiled language while Groovy is an scripting language. Java lacks of certain features that makes the life easier for developers, on the other side Groovy makes programming simple (most of the times).
But in this post what I want to show is the performance of each of them, so people (and me :) ) can decide which to use in a specific case.
Java | Groovy
2766 ms | 20121 ms
2828 ms | 19188 ms
2891 ms | 19188 ms
2969 ms | 19062 ms
2938 ms | 19281 ms
2813 ms | 20067 ms
The conditions of these test were:
IDE: Eclipse
Machine: Intel Core 2 Duo 2.1 Ghz, 3Gb RAM, Windows 7 RC
The test program was about filling a list of integers with consecutive numbers from 1 (one) to 10000000 (ten millions) , and them sum them up and showing the results.
Here is the code in Java:
import java.util.*;
public class TestJava {
public static void main(String[] args) {
long iniTime = System.currentTimeMillis();
List list = new ArrayList();
for (int i = 1; i <= 10000000; i++) {
list.add(i);
}
long sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
}
System.out.println("Java: The result is " + sum + " and took " + (System.currentTimeMillis() - iniTime) + " ms");
}
}
And the Groovy code (Pretty Simple :) ):
import java.lang.System
def iniTime = System.currentTimeMillis();
def list = []
for(i in 1..10000000){
list << i
}
long sum = 0
for(i in 0..<list.size){
sum += list[i]
}
println "Groovy: The result is ${sum} and took " + (System.currentTimeMillis() - iniTime) + " ms"
But in this post what I want to show is the performance of each of them, so people (and me :) ) can decide which to use in a specific case.
Java | Groovy
2766 ms | 20121 ms
2828 ms | 19188 ms
2891 ms | 19188 ms
2969 ms | 19062 ms
2938 ms | 19281 ms
2813 ms | 20067 ms
The conditions of these test were:
IDE: Eclipse
Machine: Intel Core 2 Duo 2.1 Ghz, 3Gb RAM, Windows 7 RC
The test program was about filling a list of integers with consecutive numbers from 1 (one) to 10000000 (ten millions) , and them sum them up and showing the results.
Here is the code in Java:
import java.util.*;
public class TestJava {
public static void main(String[] args) {
long iniTime = System.currentTimeMillis();
List list = new ArrayList();
for (int i = 1; i <= 10000000; i++) {
list.add(i);
}
long sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
}
System.out.println("Java: The result is " + sum + " and took " + (System.currentTimeMillis() - iniTime) + " ms");
}
}
And the Groovy code (Pretty Simple :) ):
import java.lang.System
def iniTime = System.currentTimeMillis();
def list = []
for(i in 1..10000000){
list << i
}
long sum = 0
for(i in 0..<list.size){
sum += list[i]
}
println "Groovy: The result is ${sum} and took " + (System.currentTimeMillis() - iniTime) + " ms"
Subscribe to:
Posts (Atom)