Synchronization of static methods

Z

zebulon

Hi,
how can I perform synchronization in a static class (only static methods and
static fields) since I cannot use the wait()/notify() method ?

What I want to do :


public class X
{
private static data // a list

public static {synchonized? }method1_read_data( .. ) // this method does
not modify the internal state of the data. Must be accessible simultaneously
by differents threads.
// However, if
method2 or method3 is being called it must wait.

public static {synchonized } method2_modify_data(..) // If method2 or
method3 is being called, it must wait.

public static {synchonized } method3_modify_data(..) // If method2 or
method3 is being called, it must wait.

}

If method2 or method3 are declared synchonized , it guarantees that only
one can be called at a time ? right ?
But if I declare also method1 synchonized, it won't be accessible by
differents threads simultaneously , will it be ?
Are there issues concerning performances of static methods'synchronization
?

Thanks for help,
OG
 
C

Chris Smith

zebulon said:
how can I perform synchronization in a static class (only static methods and
static fields) since I cannot use the wait()/notify() method ?

You can use wait() and notify() and notifyAll() just fine... you just
need an object to call the methods on.

Aside from that, the wait/notify mechanism is not required for
synchronization... so the availability of these methods isn't relevant
for use of the synchronized keyword. When you declare a static method
as synchronized, it uses the object of java.lang.Class as a
synchronization monitor. If you do need wait/notify, you can use the
Class instance for that as well.
public class X
{
private static data // a list

public static {synchonized? }method1_read_data( .. ) // this method does
not modify the internal state of the data. Must be accessible simultaneously
by differents threads.
// However, if
method2 or method3 is being called it must wait.

public static {synchonized } method2_modify_data(..) // If method2 or
method3 is being called, it must wait.

public static {synchonized } method3_modify_data(..) // If method2 or
method3 is being called, it must wait.

}

This is beyond a simple monitorenter/monitorexit, so we'll use
wait/notify for the implementation. What you're describing is basically
a read/write lock. Here's a simple implementation.

public class X
{
private static List data = new LinkedList();

private static int readers = 0;
private static int writers = 0;

public static void method1_read_data()
throws InterruptedException
{
try
{
readLock();

...
}
finally
{
readUnlock();
}
}

public static void method2_modify_data()
throws InterruptedException
{
try
{
writeLock();

...
}
finally
{
writeUnlock();
}
}

public static void method3_modify_data()
throws InterruptedException
{
try
{
writeLock();

...
}
finally
{
writeUnlock();
}
}

private synchronized void readLock()
throws InterruptedException
{
while (writers > 0) X.class.wait();
readers++;
}

private synchronized void readUnlock()
{
readers--;
if (readers == 0) notifyAll();
}

private synchronized void writeLock()
throws InterruptedException
{
while ((readers > 0) || (writers > 0)) X.class.wait();
writers++;
}

private synchronized void readUnlock()
{
writers--;
notifyAll();
}
}

Note the use of try/finally to avoid leaving the locks in place if an
operation fails in some unexpected way.
If method2 or method3 are declared synchonized , it guarantees that only
one can be called at a time ? right ?
But if I declare also method1 synchonized, it won't be accessible by
differents threads simultaneously , will it be ?

Right. Hence, the implementation above that only synchronizes
operations on a higher-level lock. The majority of code in the three
functional methods run without holding the synchronization monitor.
Are there issues concerning performances of static methods'synchronization
?

Not for simple synchronization. Obviously, as always, don't do it
unless you need it to make the program correct; but it's not implicitly
slow. The read/write lock implementation above is a performance
concern, though. Before using it, take some time to decide if it's even
worth the bother. Unless there's really a *lot* of stuff happening in
methd1_read_data, and that's a commonly called routine, and the other
two methods are called very rarely, the read/write lock is probably a
waste of time.

There are also plenty of variations on a read/write lock. You can
implement various preferences in terms of whether you prefer to give the
lock to readers or writers, whether it's possible to upgrade a read lock
to a write lock, and so forth.

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

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

zebulon

thanks for your very didactic explanations

Chris Smith said:
You can use wait() and notify() and notifyAll() just fine... you just
need an object to call the methods on.

Aside from that, the wait/notify mechanism is not required for
synchronization... so the availability of these methods isn't relevant
for use of the synchronized keyword. When you declare a static method
as synchronized, it uses the object of java.lang.Class as a
synchronization monitor. If you do need wait/notify, you can use the
Class instance for that as well.


This is beyond a simple monitorenter/monitorexit, so we'll use
wait/notify for the implementation. What you're describing is basically
a read/write lock. Here's a simple implementation.

public class X
{
private static List data = new LinkedList();

private static int readers = 0;
private static int writers = 0;

public static void method1_read_data()
throws InterruptedException
{
try
{
readLock();

...
}
finally
{
readUnlock();
}
}

public static void method2_modify_data()
throws InterruptedException
{
try
{
writeLock();

...
}
finally
{
writeUnlock();
}
}

public static void method3_modify_data()
throws InterruptedException
{
try
{
writeLock();

...
}
finally
{
writeUnlock();
}
}

private synchronized void readLock()
throws InterruptedException
{
while (writers > 0) X.class.wait();
readers++;
}

private synchronized void readUnlock()
{
readers--;
if (readers == 0) notifyAll();
}

private synchronized void writeLock()
throws InterruptedException
{
while ((readers > 0) || (writers > 0)) X.class.wait();
writers++;
}

private synchronized void readUnlock()
{
writers--;
notifyAll();
}
}

Note the use of try/finally to avoid leaving the locks in place if an
operation fails in some unexpected way.


Right. Hence, the implementation above that only synchronizes
operations on a higher-level lock. The majority of code in the three
functional methods run without holding the synchronization monitor.


Not for simple synchronization. Obviously, as always, don't do it
unless you need it to make the program correct; but it's not implicitly
slow. The read/write lock implementation above is a performance
concern, though. Before using it, take some time to decide if it's even
worth the bother. Unless there's really a *lot* of stuff happening in
methd1_read_data, and that's a commonly called routine, and the other
two methods are called very rarely, the read/write lock is probably a
waste of time.

There are also plenty of variations on a read/write lock. You can
implement various preferences in terms of whether you prefer to give the
lock to readers or writers, whether it's possible to upgrade a read lock
to a write lock, and so forth.

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

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

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,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top