?
Solved

About synchronization

Posted on 2003-03-07
10
Medium Priority
?
283 Views
Last Modified: 2010-03-31
Hi,

I have 2 classes, in which there are database access. Thus, I want to synchronize the methods in two classes, i.e. when method1 in class A is running, method1 in class B should wait until method1 in class A finished.
Could I do it in the following ways?

class A{
   public synchronized void method1(){
     ...database access...
   }
}

class B{
   public synchronized void method1(){
      ...database access...
   }
}

A million thanks ^^

Sherina
0
Comment
Question by:sherina
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 2

Expert Comment

by:functionpointer
ID: 8093401
no, you can't.  in your example your are synchronizing not only 2 different methods, but they are in 2 different classes.  This will do absolutely nothing but ruin any optimization the compiler would have done and slow your program down.

Synchronized methods mean that it can only have one caller at a time. In your example, nothing about A's method1 keeps anyone from calling B's method1.
now, if class A and class B both called the same synchronized method of class C, then they would have to wait for each other. I think this is what you were looking for.

It is not a good idea to allow multiple instances of mutliple classes to write to the database at the same time. No matter how hard you try to synchronize the methods, things like IO speed and network latency are out of your control. They will get you sooner or later.

Your best bet is to use one single 'access' class handle all your database connections (unless your readonly). It makes it alot easier to code around too.  Your A and B classes can still do SQL writes, but they should all get their connections from some general access manager. If you decided to implement pooling or locks, you could do that at the same level, without changing any other code.
0
 
LVL 2

Expert Comment

by:karlika
ID: 8094017
try this:

class Loader{
  public Loader(){//you might take any method not just the constructor
    Object lock = new Object();
    new ClassA(lock);
    new ClassB(lock);
  }
}

class ClassA{
  private Object mutex;

  public ClassA(Object lock){
    mutex = lock;
  }

  public void method(){
    synchronized(mutex){
      //database Access
    }
  }
}

class ClassB{
  private Object mutex;

  public ClassB(Object lock){
    mutex = lock;
  }

  public void method(){
    synchronized(mutex){
      //database Access
    }
  }
}

Marko
0
 
LVL 2

Expert Comment

by:karlika
ID: 8094027
A synchonized method like
public synchronized void method(){
  //some code
}

is the same as:

public void method{
  synchronized(this){
    //some code
  }
}

Where this means the current object instance of this class.
synchonized methods are primarily to avoid synchronous access to one resource of the object. E.g: In java.util.Hashtable you can't get() and remove() a value at the same time, because the methods are synchronized.

Marko
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Expert Comment

by:bkrahmer
ID: 8095499
I disagree with about 3/4 of functionpointer's answer.  From first glance, we could say that it's not a good idea to have multiple classes accessing the database at the same time.  However, there are valid reasons for doing so.  Think of functionality-specific subclasses, thread pools, and the like.

In addition, your opening statement is absolutely false.  He asked if he could synchronize methods in two different classes.  I can think of two ways off-hand.  One way is for each class to get a reference of a class which acts as a singleton.  (new SingletonMutex().getLock();)  (I would use it as a member variable actually.)  The second way is to create a super-class or an interface for the two classes which holds a Mutex-like object.

I'm not flaming, but I hate to see such misinformation being stated as fact.

thanks,
brian
0
 
LVL 2

Expert Comment

by:functionpointer
ID: 8098176
Yes, bkrahmer, it IS ok to have multiple instances or accesses to the database at the same time. I said as much. What i did say was it is not a good idea to allow multiple instances of mutliple classes to WRITE to the database at the same time.

If what you say is true,
>>However, there are valid reasons for doing so.  Think of functionality-specific subclasses, thread pools, and the like.
Try this in an app that uses more than one DB login, over a VPN or even a large enterprise network where latency is over 10 mili. You will loose control over the excecution order of the db statements. If your writes are inserts into tables with indexes, or updates to existing data, your app WILL fall on its face. I would like to see your justification for your 'valid reasons' for corrupting a database. Besides, I dont make it a habit to marry my code to my database implementation. IMO, 99% of your code should look the same whether your writing to a db, socket, or file system.


>In addition, your opening statement is absolutely false

My openning statement was based on the example posted, and i didn't see any common reference to some 'singleton' lock object in the example, nor did i see any commonly implemented interface.
lets read the question again
>when method1 in class A is running, method1 in class B should wait until method1 in class A finished.
If NO isnt the right answer to the posted question from the example posted, you really shouldn't be knocking anyone else and as far as 'misinformation', you've made it to the finals.

Your suggestion of a Singleton mutex-type lock would be nice if we could all use different VMs for every piece of every app, and if there were only ONE programmer for every system, and nothing else in that VM ever wanted to do this...


>I'm not flaming, but I hate to see such misinformation being stated as fact.

^ DITTO


karlika has the right idea about how to accomplish  synchronization with a shared mutex-like object. BUT:
>public synchronized void method(){
> //some code
>}

is nothing at all like:

>public void method{
> synchronized(this){
>   //some code
> }
>}

the first synchronizes the method. the second locks the instance while the block in the method runs. they both share the 'synchronized' keyword, and that is where the similarities end.

Sun has quick overview: http://java.sun.com/docs/books/tutorial/together/bingo/threads.html

and this is not a bad article on the subtle differences in how you synchronize things and what it means:
http://www.fawcette.com/javapro/2003_03/magazine/features/odoerderlein/default.asp

0
 

Author Comment

by:sherina
ID: 8098304
Hi,

A million thanks for the answers from you all ^^

I used Connection Pool to manage the connection of the system. And the problem i met is that when the method in class A is retriving data from database using ResultSet, method in class B runs in the middle and try to access database at the same time. And so it throws SQLException.

At last, I used something like singleton to solve the problem. I have 2 ways of writing the mutex object in mind now.

Method 1:
public class Mutex{
     static Object instance = new Object();
}

class A{
   Object mutex=Mutex.instance;
   public void a(){
      synchronized(mutex){
      }
   }
}

Method 2:
public class Mutex{          
     static private Mutex instance;    
     static synchronized public Mutex getInstance(){
          if(instance==null){
               instance=new Mutex();
          }
          return instance;
     }
}

class A{
    Mutex mutex=Mutex.getInstance();
    public void a{
      synchronized(mutex){
      }
    }
}

1. Are there difference among the two methods?
2. At first, i thought database will handle all those    
   synchronization problem. But after this problem
   appears, it seems to me that my first perception is
   wrong. Wanna ask if database will handle
   synchronization problems? or to which extent or which
   type of synchronization will database handle?
3. Is it a must to add "synchronized" to each method in a
   class for accessing database?

A million thanks thanks thanks ^^

Sherina
0
 
LVL 2

Expert Comment

by:functionpointer
ID: 8099506
The problem with using a Singleton for anything is that you only ever get one of them. You should use one only when necessary, and even then, very thoughtfully.

For instance, what if you wanted to use the same Mutex for file io? You're essentially saying an instance of Class X can't write to the disk because Class A is accessing the database. Like I said, using 1 instance of a 'data base acessor' class at least lets your object lock be specific to database activity.

Riddle me this:  What good is a connection pool going to do for you if only ONE thread can ever read/write from the database at the same time? In this scenario of the synchronized singleton mutex, considering you are getting the lock before your call from to the connection pool and returning it before returning the connection, how many connections will your pool ever need to have? (Answer: 1)

Depending on your database and the information in it, this will actually hinder your performance. You may want one class that can write to tables a, b and c, and another class that can write to tables d, e, and f. What do they have to do with each other? Nothing, so why should they have to wait for each other?

On the other hand, you have one DatabaseAccess(singleton?) class that may have a connection pool for performance. This DatabaseAccess class has an instance of an ABCTableAccess class and a DEFTableAccess class, each which gets a connection from the pool and has it's own mutex-type lock that prevents concurrent reads/writes to their respecive data. Now you can write ABC data without locking DEF data access, and visa-versa. This is also one example showing the Singleton mutex-type lock is very bad idea.

Regarding #3: No, you dont. As a matter of fact, you should try NOT to. As synchronization goes, its the worst. You are better off locking an object instance than a method.

What is right for you is really up to you and your app design/arch. Its a pretty good rule of thumb to second guess yourself anytime you type the keyword 'synchronized'.  It is probably the least understood and most misused concept in Java.  Good luck. :)
0
 

Author Comment

by:sherina
ID: 8117935
Hi Functionpointer,

Thanks for your detailed explanations. I feel much clear about the concepts.

But still have something don't understand right now in the area of database accesses using Java.

1. To my first impression, database can handle different kinds of synchronization problems(say 2 accesses are writing to the same tables at the same time)? Am I right?
As I'm thinking about when there are 2 persons who are using sqlplus to update the same table, Oracle can still handle the case. Then why it is not the same case when writing programs?

2. Referring to my previous message (the mutex codes), I think method 1 can still get a singleton. Why people always use method 2 to write singleton? (I found it in some sample codes) To me, it seems method 1 is more neat and clear.  

Thanks a lot ar ^^

Sherina
0
 
LVL 2

Accepted Solution

by:
functionpointer earned 80 total points
ID: 8125411
>Then why it is not the same case when writing programs?

The problem isn't in the database. That works just fine. Because externally, it behaves SINGLE threadedly. Our programs are the multi-threaded beasts that make things confusing.

It's when we try to mirror data outside the database, like reading a ResultSet into a container object, that we get in trouble. Let's say you read a result set into a data container object, do something with the object, alter the object and then try to write the data back to the database (sometimes this may not occur for some time, or even in the same thread, like in servlets, for example ). Your really not going to lock rows (if your database and driver allow) while waiting for client input. If supported, you could lock rows just prior to writing and do some validation on the database data and exception if your container's data is deemed dirty. That's not only complicated, but not a functional app at that point because it failed to do its job.

It gets much more complicated and the problem becomes more evident when you have multi-layered container objects populated from different tables, or even diffent databases.

If you are using a relational database to store your data in a logical manner, it seems your containers would mimic their structure somewhat. Its easy to forget that there's  no persistance between our containers and our databases (usually, that is. see JDO,CMP). You can build your database access around your database schema/container object structure. Then synchronize access on this level via a ContainerObjectFactories that produced container objects with the same mutex-type locks where appropriate.
ABC's can do abc things. DEF's can do def things. You could even synch them down to a specific parent record id if your database was 3NF ( this is kinda extreme, just pointing it out ). The important thing is: all access in and out of the database happen at the same place. You can use as many threads as you want. Just make sure all the threads are using the same logic ( ie, passing through the same database access module or the like ).

JDBC is not a wonder drug. Just database access. Like I said, it depends on your app. This might be good info for now, might be good on your next project, might be never think of it again. ;-)


>I think method 1 can still get a singleton
In method 1, there is nothing that makes the Mutex instance unique. Therefore, "new Mutex()" will always return a brand new instance of a Mutex. To synchronize on this would mean nothing, because another synch block may be locking a completely different Mutex instance.

Every instance of Mutex WILL contain reference to the same static member Object instance, and
synchronized( Mutex.instance )
{
}
would be effective synchronization, but method 1 is just not a good class ( public members ), and if you are going to make them private and add a 'get' method, you may as well make a proper singleton class.

method 2 isnt really a singleton. It must have a private constructor only accessed by getInstance(). A singleton guarantees there are NO other ways to create an instance and that there will ever be only one. That is why they must be written this way.
0
 

Author Comment

by:sherina
ID: 8126503
Hi Functionpointer,

Great, I got the idea now.
Thanks a lot ^^

Sherina
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
The viewer will learn how to implement Singleton Design Pattern in Java.
Suggested Courses
Course of the Month11 days, 5 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question