Link to home
Start Free TrialLog in
Avatar of sherina
sherina

asked on

About synchronization

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
Avatar of functionpointer
functionpointer

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.
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
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
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
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

Avatar of sherina

ASKER

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
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. :)
Avatar of sherina

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of functionpointer
functionpointer

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of sherina

ASKER

Hi Functionpointer,

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

Sherina