is this correct use of synchronized?

J

Jeff

midp 2.0
Java SE 5.0
J2ME version 2.2

Is this correct use of synchronized?
NB: methods like startApp are needed to get the code below to work, I know
that....

public class Test extends MIDlet implements Runnable;
{
private boolean helloworld;

public Test() {
helloworld = false;
display = Display.getDisplay(this);
Thread thread = new Thread(this);
thread.start();
synchronized (this) {
helloworld = false;
}
}

public void run() {
synchronized (this) {
helloworld = true;
}
}
}
 
C

Chris Smith

Jeff said:
Is this correct use of synchronized?
public class Test extends MIDlet implements Runnable;
{
private boolean helloworld;

public Test() {
helloworld = false;
display = Display.getDisplay(this);
Thread thread = new Thread(this);
thread.start();
synchronized (this) {
helloworld = false;
}
}

public void run() {
synchronized (this) {
helloworld = true;
}
}
}

What are you trying to do? Since the field 'helloworld' is never read
in the code you posted, it would be difficult to classify the use as
either "correct" or "incorrect". From what threads and from what code
do you read the value of the 'helloworld' field?

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Jeroen V. said:

And there's this newsgroup, which I hope turns out to be a helpful
resource for people who come here with questions. Pointing someone to a
resource that helps with a question is one thing... but this was a
question that is simply not answered by basically telling someone to go
search Google, or by a vague reference to the Java Glossary. Thread
synchronization problems in particular tend be of the type that require
sophisticated reasoning, and a definition of what 'synchronized' does or
examples from very different contexts are unlikely to be appropriate.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Jeff

Thanks for your reply


I modified the code a bit, instead of showing an example code I instead
posted a real scenario I've having problems with. My trouble is with the
threads. the variable "scanning" is set to TRUE in void Scan() and the last
thing done in the run() method is setting scanning = FALSE... the Paint
method will print out TRUE to the debug window if scanning is TRUE, but it
prints FALSE instead - it doesn't print TRUE even if the run is busy in the
FOR-loop either.

I've been looking into this problem for a couple of days and I got stuck...
I think this error is related to synchronization but I honestly cannot find
out what is causing this problem. So please tell me what I must change in my
code to make it work...

The method calling Scan isn't shown, but it's done when the user pushes the
# key on the handset

This doesn't work when I compile and run it on emulator from Nokia.... I
mean this code runs but it doesn't run as I want it to... I don't get any
compile errors, if I get compile errors I wouldn't be able to run it...


package com.test;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.microedition.io.*;

class testManager extends javax.microedition.lcdui.game.LayerManager
implements Runnable
{
public boolean scanning = false;
public testManager(int width, int height) throws Exception {
}

//Methods
public void paint(Graphics g) {
synchronized (this) {
if (scanning) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
}
paint(g, 0, 0);
}

public void Scan() {
strInfoText = "helloworld3";
synchronized (this) {
scanning = true;
}
Thread thread = new Thread(this);
thread.start();
}

public void run() {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
synchronized (this) {
scanning = false;
}
}
}
 
T

Thomas Hawtin

Jon said:
Generally synchronizing one atomic operation is meaningless. As far as I
can tell, the usage of synchronized in this code does nothing.

Not really. It allows other threads to access data in a more complex
way. Also without volatile/synchronisation, you have no happens-before
relationships, so don't know when other threads will see changes. You
can also create an object outside of a synchronised block and update a
reference to it within such a block, and still end up with everything
properly synchronised.

Tom Hawtin
 
J

Jeroen V.

Chris said:
And there's this newsgroup, which I hope turns out to be a helpful
resource for people who come here with questions.

Given the fact that the question is well documented.
Pointing someone to a
resource that helps with a question is one thing... but this was a
question that is simply not answered by basically telling someone to go
search Google, or by a vague reference to the Java Glossary.

Okay, maybe I should have asked what Jeff wanted to reach, but when you
hope for an answer you should post questions that describe the problem &
its context thoroughly. I could have answered "Is this correct use of
synchronized?" with: "yes if it compiles"...
Thread synchronization problems in particular tend be of the type that require
sophisticated reasoning, and a definition of what 'synchronized' does or
examples from very different contexts are unlikely to be appropriate.
You're right, but as I stated before, in my opinion the context wasn't
very clear.
 
J

Jon Martin Solaas

Jeff said:
Thanks for your reply


I modified the code a bit, instead of showing an example code I instead
posted a real scenario I've having problems with. My trouble is with the
threads. the variable "scanning" is set to TRUE in void Scan() and the last
thing done in the run() method is setting scanning = FALSE... the Paint
method will print out TRUE to the debug window if scanning is TRUE, but it
prints FALSE instead - it doesn't print TRUE even if the run is busy in the
FOR-loop either.

Generally synchronizing one atomic operation is meaningless. As far as I
can tell, the usage of synchronized in this code does nothing.
I've been looking into this problem for a couple of days and I got stuck...
I think this error is related to synchronization but I honestly cannot find
out what is causing this problem. So please tell me what I must change in my
code to make it work...

The method calling Scan isn't shown, but it's done when the user pushes the
# key on the handset

So we have one instance of testManager (should be TestManager, really,
and methods should start with lowercase instead ... ), and one thread
running the Scan method, or could # be pushed several times spawning
several threads? Let's assume that's a possibility.
This doesn't work when I compile and run it on emulator from Nokia.... I
mean this code runs but it doesn't run as I want it to... I don't get any
compile errors, if I get compile errors I wouldn't be able to run it...

When scanning is set to true or false within a synchronized block, there
is nothing preventing some other thread to re-set it to something else
immediately after the last instruction in the synchronized block has
completed.

If the user pushes # two times the first thread will set scanning=true
and the second thread will do the same at a slightly later point in
time. Then the first thread will end the for-loop, set scanning=false
and terminate. The second thread may still be running in the for-loop in
the scanning method, while scanning actually is false already. If paint
is called at this point the output would be FALSE.
package com.test;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.microedition.io.*;

class testManager extends javax.microedition.lcdui.game.LayerManager
implements Runnable
{
public boolean scanning = false;
public testManager(int width, int height) throws Exception {
}

//Methods
public void paint(Graphics g) {
synchronized (this) {
if (scanning) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
}
paint(g, 0, 0);
}

public void Scan() {
strInfoText = "helloworld3";
synchronized (this) {
scanning = true;
}
Thread thread = new Thread(this);
thread.start();
}

public void run() {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
synchronized (this) {
scanning = false;
}
}
}

try this

Boolean scanning = new Boolean(false);

public void scan()
{
Thread thread = new Thread(this);
thread.start();
}

public void run() {
synchronized(scanning) {
scanning=new Boolean(true);
for (int i = 0; i < maxScan; i++) {
Scanner.scan(i);
System.err.println("Now scanning i = " + i);
}
System.err.println("Done scanning");
scanning=new Boolean(false);
}
}

Any code accessing the scanning variable in this instance of the
testManager class will see the false value because scanning is only true
within the synchronized block where other code is locked out from
accessing the object scanning (it needs to be Boolean and not boolean
to lock it). Ofcourse this is under assumption that the scanning
variable is not set to true somewhere else in the code outside the
synchronized block.

I'm not at all sure this is really what you need to do, I know too
little of what your app is really doing. Maybe this will introduce new
locking problems for you.
 
J

Jon Martin Solaas

Thomas said:
Not really. It allows other threads to access data in a more complex
way. Also without volatile/synchronisation, you have no happens-before
relationships, so don't know when other threads will see changes. You
can also create an object outside of a synchronised block and update a
reference to it within such a block, and still end up with everything
properly synchronised.

Tom Hawtin

That was all very blurry to me. But I'm no synchronization wizard. Would
you care to explain in detail what would be the difference if all the
synchronization blocks in the code in this news-thread (not execution
thread :) were removed? Exactly what's the difference between

scanning=false;

and

synchronized (this) {
scanning=false;
}

?

What kind of happens-before-relationships are present in the latter, but
not in the first part here (or in the posted code if this example is to
simple)?
 
C

Chris Smith

Jon Martin Solaas said:
That was all very blurry to me. But I'm no synchronization wizard. Would
you care to explain in detail what would be the difference if all the
synchronization blocks in the code in this news-thread (not execution
thread :) were removed? Exactly what's the difference between

scanning=false;

and

synchronized (this) {
scanning=false;
}

?

The difference is that with the first, there's no guarantee at all as to
when another thread that reads 'scanning' will see its value as false.
With the latter, any thread that enters a synchronization block on the
object first and THEN reads 'scanning' is guaranteed to see its value as
being false.

This is not an easy thing to understand, unfortunately. The chapter of
the JLS that explains it is one of the most difficult in the whole book
(perhaps not quite so bad as the part about type inference for generic
method invocations without explicit type arguments). In essence,
though, when evaluating multithreading correctness you should stop
thinking in terms of a variable having only one value. It may have a
different value from the perspective of any thread; and it may have any
number of values, of which the variable may evaluate to any of them,
arbitrarily, when used as a value. The only way to avoid this is to use
the volatile or synchronized keywords. In this case, volatile would
have been sufficient. However, synchronized works as well.

What synchronized does is to establish a "happens-before" relationship.
That simply means that one action of the code is guaranteed to have
happened before another, and the results of the first statement are
therefore visible to the second. Entering or leaving a synchronized
block establishes such a "happens-before" relationship with another
thread that enters or leaves that same block. Therefore, the values
written to variables from the first thread are visible to the second.
Without the synchronization actions, there would be no such
relationships and it would be entirely possible for the second thread to
continue to read whatever value 'scanning' had when the thread was
started. (Because thread creation DOES establish such a "happens-
before" relatonship, it would not be possible for the second thread to
read a value of scanning from some time before the thread creation.)
What kind of happens-before-relationships are present in the latter, but
not in the first part here (or in the posted code if this example is to
simple)?

The original code without the synchronized statements establishes only
one significant happens-before relationship: namely, that the call to
thread.start() happens-before the first action of the new thread. There
are a HUGE number of other such relationships, due to the fact that
within a single thread each action of code happens-before any action of
code that comes after it; either in order of operations within an
expression, or in a subsequent statement. However, it's easier to not
mention those until they are needed, considering them obvious.

The code with the synchronized statement establishes those happens-
before relationships, plus additional happens-before relationships that
say that one thread exiting a synchronized block happens-before another
thread entering that block. These additional relationships are neeeded
to guarantee that changes to the 'scanning' variable made from run()
(and perhaps from Scan() if it's not called from the graphics thread)
are visible inside of paint(Graphics).

Does that help, or confuse you more?

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
G

Gordon Beaton

Exactly what's the difference between

scanning=false;

and

synchronized (this) {
scanning=false;
}

What kind of happens-before-relationships are present in the latter,
but not in the first part here (or in the posted code if this
example is to simple)?

Assuming that the assigment is atomic, there is still no guarantee
that a thread reading the value of scanning will see the latest
assigned value unless there is a barrier between the assignment and
the subsequent read. You get a barrier by declaring the variable
"volatile" or accessing it from within a synchronized block.

/gordon
 
J

Jon Martin Solaas

Chris said:
Does that help, or confuse you more?

PS, and more importantly, what is the exact problem with the code from
OP? He has the synchronized blocks and still doesn't get the expected
result.
 
J

Jeff

Thanks for your help, I've done a few changes to the 'run' method and still
I have the same problem, I've been testing this code for a while and it
seems like while the 'run' method is running the 'paint' method is called
many times. the 'paint' method reads 'scanning' as FALSE, while 'run' is
running and 'scanning' have got the value TRUE inside 'run'....


package com.test;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.microedition.io.*;

class testManager extends javax.microedition.lcdui.game.LayerManager
implements Runnable
{
public boolean scanning = false;
public testManager(int width, int height) throws Exception {
}

//Methods
public void paint(Graphics g) {
synchronized (this) {
if (scanning) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
}
paint(g, 0, 0);
}

public void Scan() {
strInfoText = "helloworld3";
synchronized (this) {
scanning = true;
}
Thread thread = new Thread(this);
thread.start();
}

public void run() {
synchronized (this) {
if (scanning) {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
scanning = false;
}
}
}
}


This code generate this output to the debug window....
The FALSE are written by the paint method.....

FALSE
FALSE
TESTING 0
TESTING 1
TESTING 2
TESTING 3
TESTING 4
TESTING 5
TESTING 6
TESTING 7
TESTING 8
TESTING 9
scan done
FALSE
FALSE
FALSE
FALSE
FALSE


But when I modified run, removed this statement:
scanning = false;

Now the result gets as shown below

FALSE
FALSE
FALSE
FALSE
TESTING 0
TESTING 1
TESTING 2
TESTING 3
TESTING 4
TESTING 5
TESTING 6
TESTING 7
TESTING 8
TESTING 9
scan done
TRUE
TRUE

In my humble opinion this means that this statement :
synchronized (this) {
scanning = true;
}
works okay....

BUT, while the 'run' method is running the 'paint' method is called many
times. the 'paint' method reads 'scanning' as FALSE, while 'run' is running
and 'scanning' have got the value TRUE inside 'run'....

What must I change so that the 'paint' reads the value 'scanning' have while
'run' is running?

Jeff
 
J

Jeff

public void run() {
synchronized (this) {
if (scanning) {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
scanning = false;
}
}
}

It seems like 'scanning = false;' get executed before the for-loop. To me
this is very strange behavior, 'scanning = false;' is under the for-loop and
I thought that the for-loop would be executed before the 'scanning = false;'
statment

If I remove the statment 'scanning = false;' from 'run' then it works, I
mean that while the for-loop is executing the 'paint' method reads the value
'scanning' has before set to FALSE, in other words it reads the value TRUE

But if the statment 'scanning = false;' is removed the program can't tell
when the thread is done executing...I want 'scanning' to be set back to
FALSE when the for-loop is finished OR when the thread is done executing

maybe using wait(), notify() or notifyAll() can help???, I'm not sure how to
apply them....

I'm not sure how to fix this so I would appreciate any tips helping me solve
this problem

Jeff
 
C

Chris Smith

Jeff said:
public void run() {
synchronized (this) {
if (scanning) {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
scanning = false;
}
}
}

It seems like 'scanning = false;' get executed before the for-loop.

No, it gets executed after the for loop. The problem is that no paint
calls can finish until the for loop is done, since the entire loop is in
a synchronized block and paint contests for that same monitor. So once
the new thread you're creating successfully gains the monitor, it
doesn't let go and let a paint happen until after it has set scanning
back to false again.

Unfortunately, we're dealing with a very vague situation here. I'm not
clear on what behavior you actually want to see, so it's hard to make
recommendations on how to get there. However, one possibility may be
that you only want to obtain a synchronized block around the assignment
to the scanning variable, rather than around the entire loop.
maybe using wait(), notify() or notifyAll() can help???, I'm not sure how to
apply them....

I haven't seen anything YET that suggests these would be needed; but
you're also a long way from my understanding what you want to do.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Jeff

Hey, thanks for your post!

I modified 'run' a bit, see below.... now a copy of 'scanner' is created in
the first synchronized block and the rest of the method uses this copy ...
the last thing this method now does is establishing a synchronized block and
set the 'scanner' back to false;

What I'm trying to do is that while this midlet is running a status line at
the bottom of the screen, I want this status line to show the status about
the midlet is doing.... So when 'scanner' is TRUE I want it to display a
text telling it is doing this 'run' method....

Any suggestion to what I must change in my code so that 'paint' draw the
correct status will be greatly appreciated. What status the 'paint' draw is
directly related to the 'scanner' variable, because a if-test in 'paint'
determine what will be displayed - if (scanner) {

public void run() {
boolean ecopy;
synchronized (this) {
ecopy = scanning;
}
if (ecopy) {
for (int i=0; i<10; i++) {
System.out.println("TESTING " + i);
}
System.out.println("scan done");
synchronized (this) {
scanning = false;
}
}
}
}
 

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

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,079
Latest member
ElidaWarin

Latest Threads

Top