• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

Java synchronization help needed

tfinch2

Lifer
So I have a class that extends Thread, and when I start the thread, it changes some variable values in a static class then uses them in some methods from that class. Whoever wrote the static class did not synchronize this code, so If I start both threads right away, they will overwrite the static values in each thread and muck everything up.

/* BAD */
Test a = new Test();
Test b = new Test();
a.start();
b.start();

As a fix, I added an init method (due to requirements it can't be in the constructor) so that code block will run serially before multiple threads start.

/* Okay, but ugly */
Test a = new Test();
Test b = new Test();
a.init();
b.init();
a.start();
b.start();

To me this is ugly and seems kind of fragile if someone else decides to use this same class later (might not understand the behavior and overlook this). I'm not sure if in my run method I could do a synchronized code block because there are two different instances of the same class and the separate threads won't really care if it's synchronized (I may be wrong about this).

I'm sure there is a simple solution to this problem because it seems like it might occur fairly often, but it's late and I'm tired of screwing with this code quite frankly.

Any advice?
 
When using synchronized, you need to find some Object that the Objects to be synchronized have in common. You can synchronize on any static Object in Test, or even add one (e.g. static Object syncOnMe = new Object😉.
 
I would then think you can synchonize on an object, specifically the static object, instead of the method. Then, only one thread will have access to it.

DanceMan
 
Originally posted by: Ken_g6
When using synchronized, you need to find some Object that the Objects to be synchronized have in common. You can synchronize on any static Object in Test, or even add one (e.g. static Object syncOnMe = new Object😉.

Can it be the Test object itself?

public class Test extends Thread
{
public void run()
{
synchronized(Test.class)
{
//do critical section stuff
}
run_other_stuff();
}
}

or I suppose I could just as well do...

public class Test extends Thread
{
private static Object lock = new Object();
public void run()
{
synchronized(lock)
{
//critical section
}
run_other_stuff();
}
 
Originally posted by: tfinch2
Originally posted by: Ken_g6
When using synchronized, you need to find some Object that the Objects to be synchronized have in common. You can synchronize on any static Object in Test, or even add one (e.g. static Object syncOnMe = new Object😉.

Can it be the Test object itself?

public class Test extends Thread
{
public void run()
{
synchronized(Test.class)
{
//do critical section stuff
}
run_other_stuff();
}
}

or I suppose I could just as well do...

public class Test extends Thread
{
private static Object lock = new Object();
public void run()
{
synchronized(lock)
{
//critical section
}
run_other_stuff();
}

The first example it might work, but it seems to be a mis-use of the Test.class object. Your second example is better and should work, but be careful -- you really should reference only those static objects that do need to be synchonized, since your run_other_stuff() CAN have a reference to the lock object. You can also just declare the sychronized(lock) in it's own synchonized method, and then call that method and the run_other_stuff() back-to-back.
 
you can do some thing like this:

public class Test {
private static Object lock;

public static changeStaticStuff() {
synchroinzed (lock) {
// change your static stuff here
}
}
}

and call Test.changeStaticStuff from ur Thread objects' run().
 
Originally posted by: statik213
ignore my previous post, looks like u already had my suggestion... did it work ok?

I got it going using a static Object. :thumbsup:

This is my first non-academic rendezvous with threading, and if you're not careful things can bite you in the ass!
 
Originally posted by: DanceMan
The first example it might work, but it seems to be a mis-use of the Test.class object. Your second example is better
I strongly dislike the second method because it hides the lock object. The lock object should be accessible to anyone who might want to do thread-sensitive things to the static class. Lacking the ability to properly synchronize the static class, I'd take the next closest thing and synchronize on the static class itself. That way, if some completely different class wants to do thread-sensitive things, it doesn't have to be co-ordinate itself directly with Test instances.
 
Originally posted by: kamper
Originally posted by: DanceMan
The first example it might work, but it seems to be a mis-use of the Test.class object. Your second example is better
I strongly dislike the second method because it hides the lock object. The lock object should be accessible to anyone who might want to do thread-sensitive things to the static class. Lacking the ability to properly synchronize the static class, I'd take the next closest thing and synchronize on the static class itself. That way, if some completely different class wants to do thread-sensitive things, it doesn't have to be co-ordinate itself directly with Test instances.

^

That's what I was going to say. I second this. Why don't you just synchronize on the "static" class in question?

Also, it is much more common to implement Runnable than to extend Thread for a class that needs to run as a thread. You can only extend one superclass in Java but you can implement unlimited interfaces. If you extend thread, you cannot have your class extend any other class if you need to or want to.
 
Originally posted by: ahurtt
Why don't you just synchronize on the "static" class in question?

Looks like I'm learning my something new for the day. 🙂

Exactly how does one do this? "synchronized(static MyClass)"? I can't imagine that's the right syntax.
 
No. The notion of a "static" class is a little bit erroneous. You can't actually put the"static" modifier in in front of your class declaration when you are authoring a new java class. I think what people mean when they refer to a "static" class is a java class which has only static methods/variables and no instance methods.

A synchronized instance method can obtain a lock on a class like:

synchronized(ClassName.class) {
// body
}

Points to remember:
- locking an object does not automatically protect access to static fields
- protecting static fields requires a synchronized static block or method
- static synchronized statements obtain a lock on the Class vs an instance of the class

And don't feel bad if you feel confused because threading and synchronization are considered confusing topics to learn. It is a very nuanced art to say the least. I am still struggling with it some myself. But it is starting to become clearer. Learning to write thread safe code is a topic covered in the "advanced" section of many a java book.
 
Originally posted by: ahurtt
- protecting static fields requires a synchronized static block or method
This doesn't quite make sense to me. Why would you need to be a static block or a static method to synchronize access to a static field?
 
I assume for the same reason you cannot access a classes instance fields/methods or the "this" object directly from a static method. Static members belong to the class, not to instances. The class itself is not the same as an instance of the class or "object." Therefore, as per the first point - locking an object does not automatically protect access to static fields. I guess you could think of it as every instance of a class has it's instance lock and every class itself has a static lock.
 
Back
Top