ExecuterService and Futures not thread save with 8 processors

L

Lew

getCurrParameterBlock() returns a reference, simply a global
ParameterBlock, which can be set by other methods. First, the
ParameterBlock defines the parameters, which are quite identical for
each image, so it isn't a problem if this variable is global. Second
an image pi is added wich must be local because of thread savety.
So, with the first line
ParameterBlock pb;  //pb is local

pb is a pointer that does not yet point to anything (not even 'null').
then with
pb = IqmTools.getCurrParameterBlock();  //pb isn't local any more,
it's global?, really?

That depends. What gets returned by the method? If it's a pointer to
a parameter block that other modules or threads also point to, then
that block instance is shared.

Consider this. Suppose you and a co-worker are both pointing to the
same desk. How many pointers are there? How many desks?
// a local image is added but pb is global? I'm not really convinced
at this point.
pb.addSource(pi);

If 'pb' points to the same parameter block as someone else's pointer,
then both pointers point to a parameter block that has the same image
as a "source".
I'll try the clone method for a thread save [sic] copy. I'll post the
results.

'clone()' is probably not the answer. You'd be better off using the
'new' operator for most use cases. 'clone()' introduces its own
problems.
 
H

helaha

getCurrParameterBlock() returns a reference, simply a global
ParameterBlock, which can be set by other methods. First, the
ParameterBlock defines the parameters, which are quite identical for
each image, so it isn't a problem if this variable is global. Second
an image pi is added wich must be local because of thread savety.
So, with the first line
ParameterBlock pb;  //pb is local

pb is a pointer that does not yet point to anything (not even 'null').
then with
pb = IqmTools.getCurrParameterBlock();  //pb isn't local any more,
it's global?, really?

That depends.  What gets returned by the method?  If it's a pointer to
a parameter block that other modules or threads also point to, then
that block instance is shared.

Consider this.  Suppose you and a co-worker are both pointing to the
same desk.  How many pointers are there?  How many desks?
// a local image is added but pb is global? I'm not really convinced
at this point.
pb.addSource(pi);

If 'pb' points to the same parameter block as someone else's pointer,
then both pointers point to a parameter block that has the same image
as a "source".
I'll try the clone method for a thread save [sic] copy. I'll post the
results.

'clone()' is probably not the answer.  You'd be better off using the
'new' operator for most use cases.  'clone()' introduces its own
problems.

Dear all,
with the help of you the problem is now pinned down and has already
been solved. It was indeed my prossImage method and especially the
ParameterBlock. Nevertheless and surprisingly the clone() method
solved the problem. Several runs of an image stack with 50 images have
been successful. Additionally I changed to ParameterBlockJAI, but not
because of thread issues.

The thread save solution is now:

public static Object processImage(PlanarImage pi){

String currFunc = IqmTools.getCurrImgProcessFunc();
ParameterBlockJAI pb = IqmTools.getCurrParameterBlock(); //not thread
save
pb.removeSources();
ParameterBlockJAI pb2 = (ParameterBlockJAI) pb.clone(); //thread
save
//ParameterBlockJAI pb2 = pb; //wouldn’t be thread safe
pb2.addSource(pi);

Object ob = JAI.create(currFunc, pb2, null);
return ob;
}

Again thank you very much for your kind help, I’ve learned a lot as a
newbie in Java.
Helmut
 
T

Tom Anderson

with the help of you the problem is now pinned down and has already
been solved. It was indeed my prossImage method and especially the
ParameterBlock. Nevertheless and surprisingly the clone() method
solved the problem. Several runs of an image stack with 50 images have
been successful.
Excellent.

Additionally I changed to ParameterBlockJAI, but not because of thread
issues.

The thread save solution is now:

public static Object processImage(PlanarImage pi){

String currFunc = IqmTools.getCurrImgProcessFunc();
ParameterBlockJAI pb = IqmTools.getCurrParameterBlock(); //not thread
save
pb.removeSources();
ParameterBlockJAI pb2 = (ParameterBlockJAI) pb.clone(); //thread
save
//ParameterBlockJAI pb2 = pb; //wouldn?t be thread safe
pb2.addSource(pi);

This is exactly the kind of thing you need to look for when probing thread
safety. The analogue in the example code i posted would be the 'dims'
variable - the variable itself is local, but its value is derived from a
global object, so different instances of that local variable in different
threads will alias each other, and thus enable inter-thread clobbering.
Tricky stuff, eh?

tom
 
H

helaha

Tom said:
Examples:

public class ManagerJ {
private static int width;
private static Map<String, Object> currentImageInfo;

public static Object processImage(Image pi) {
int height = pi.getHeight();
width = pi.getWidth();
currentImageInfo = new HashMap<String, Object>();
List<Integer> dimensions = new ArrayList<Integer>();
dimensions.add(height);
dimensions.add(width);
currentImageInfo.put("DIMENSIONS", dimensions);
doubleDimensions();
}
private static void doubleDimensions() {
List<Integer> dims = (List<Integer>)currentImageInfo.get("DIMENSIONS"):
dims.set(0, dims.get(0) * 2);
dims.set(1, dims.get(1) * 2);
}

}

In that code, 'height' is the only threadsafe variable. All of the others
are vulnerable to inter-thread clobbering: width is global,
currentImageInfo is global, dims is local but derived from a global, and
dimensions is local, but its value is aliased by dims, which is vulnerable

Dear Tom,
dear Lew,
you are exactly right. But is there a general way to derive really
loacal variables? Lew, you mentioned to use the new method. I think
that's not possible in every case. With ParameterBlock the clone()
method worked. But clone() should have some issues or other troubles?
Would it work with dims too?
e.g.
List<Integer> dims = (List<Integer>)currentImageInfo.get
("DIMENSIONS");
List<Integer> dims2 = dims.clone();

regards,
Helmut
 
L

Lew

helaha said:
you are exactly right. But is there a general way to derive really
loacal variables? Lew, you mentioned to use the new method [sic].

'new' is not a method.
I think that's not possible in every case. With ParameterBlock the clone()
method worked. But clone() should have some issues or other troubles?
Yes.

Would it work with dims too?
e.g.
List<Integer> dims = (List<Integer>)currentImageInfo.get
("DIMENSIONS");

Why do you need the cast? Isn't 'currentImageInfo#get()' generic?
List<Integer> dims2 = dims.clone();

Did you try it?

I'm a little surprised if that worked, since 'clone()' is not a public
method of 'List'.

'clone()' makes a shallow copy - it clones the 'List' but not the
items in the 'List'.

Since 'Integer' is immutable there is no risk. There is also:

List <Integer> dims2 = new ArrayList <Integer> ();
dims2.addAll( dims1 );

Either way you are making a defensive copy.

You'd create a new object when you don't necessarily need to copy the
contents of another object. You'd only use 'clone()' when you
specifically want to make a new object with the same contents as the
original object.

If the contents are mutable, you do not have thread safety with 'clone
()'. For example:

ArrayList <Foo> original = Bax.getList(); // Foo is mutable
List <Foo> copy = original.clone(); // not thread-safe!

With 'new', and without copying another object, you are guaranteed
that the new object is local and does not share state.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top