Is it possible to synchronize data members and not methods? - java

After reading topics here about Java synchronized methods, I've tried to implement it in my multiplayer game because many threads are opened and trying to access the same resource.
I've made methods synchronized but that's doesn't help me since if I have a data member called ArrayList clientConnection; and the methods that are available are:
int getArrayListSize() {
clientConnection.size();
}
void addConnection(ServerConnection i_connection) {
clientConnection.add(i_connection);
}
void removeConnection(ServerConnection i_connection) {
int index = clientConnections.indexOf(i_Connection);
clientConnections.remove(index);
}
ServerConnection getClientFromArrayListByIndex(int i_Index) {
ServerConnection client = this.clientConnections.get(i_Index);
}
I've tried to make a global synchronized method to whenever one want to use one of the methods he needs to pass in an operation type and other data and he locks the function.
The problem is that there are 2 function that return void, 1 returns int and 1 returns ServerConnection so I can't create that global method.
My question if there is a possible to lock data members and not methods in Java so I can lock the clientConnection data member?
Thanks.

If you make all these methods synchronized, then only one thread at a time will be able to invoke any of the methods, and the list will thus be accessed in a thread-safe way, provided only these methods are able to access the list (i.e. the list is private, and no other method uses the list).
synchronized int getArrayListSize() { ... }
synchronized void addConnection(ServerConnection i_connection) { ... }
etc.

You can synchronize a function by using the synchronized keyword. For example:
synchronized ServerConnection getClientFromArrayListByIndex(int i_Index) {
ServerConnection client = this.clientConnections.get(i_Index);
// ...
}

If you have one class you can simply prefix your methods with synchronized; then there is only one thread in any of those methods. But please think if you need this really; it could slow the execution. If you have public fields you should make them private and create getter methods.

You could use Collections.synchronizedList() to wrap your List in one for which all of the methods are synchronized.
Whether this is better than synchronizing the methods in your class depends on what else your methods do, and if those things also need to be coordinated.

Related

What are the impacts of using Object.class lock in synchronized block?

I am trying to synchronize read write operations on xml file from multiple methods in multiple classes. To achieve this, I am synchronizing this operations by using class level lock.
Code sample:
Test1.java:
public class Test1 {
public void method1() {
synchronized(CommonUtility.class) {
SomeObject someObject = testDAO.readSomething();
.
.
.
testDAO.writeSomething(someObject);
}
}
}
Test2.java
public class Test2 {
public void method2() {
synchronized(CommonUtility.class) {
SomeObject someObject = testDAO.readSomething();
.
.
.
testDAO.writeSomething(someObject);
}
}
}
To achieve this class level lock, consider following sample code:
synchronized(CommonUtility.class) {
.
.
.
}
What are the impacts of using Object.class instead of CommonUtility.class, like:
synchronized(Object.class) {
.
.
.
}
I think both approaches aren't ideal.
First of all, this here suggests:
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class.
In other words: when you use synchronized(CommonUtility.class) you implicitly get "synchronized" with all static synchronized methods within CommonUtility. And worse: imagine that class has no such methods today. But next week, someone adds such a static synchronized method in that utility class, assuming that only calls to that method go through that monitor. Worst case, that could lead to some ugly (runtime only) surprises.
Then: going for even broader scope (by using Object.class) makes things worse.
My answer: avoid using class objects in the first place.
IMO, the idea of "class level" lock and "object level" lock is distracting. There is only one underlying synchronization mechanism in Java: synchronized (o) { ... } where o can be any Java object (Note that in Java MyClass.class is an object.)
When you write,
synchronized SomeType foobar(...) { ... }
That's really just a shortcut way of using an instance as the lock object that protects its own member variables.
SomeType foobar(...) {
synchronized (this) {
...
}
}
Same goes for so-called "class level" locking: It's just a shorthand way of using the class itself as the lock object that protects its own static members.
Speaking of which...
Good practice keeps the lock object near the data that it protects (for some definition of "near"). If the data are private, then the lock object ought to be private. If the data are members of some instance, then the lock object ought to be members of the same instance, etc.
Object.class isn't particularly "near" anything. It will work as well as any other object, but using it makes your code harder to understand, because the reader will spend time wondering what motivated you to choose Object.class, and wondering whether your choice was based on a misunderstanding.
My own preference, for protecting instance members, looks like this:
class MyClass {
private final Object lock = new Object();
private SomeType someVariableThatNeedsProtection = ...;
private SomeOtherType someOtherVariableThatAlsoNeedsProtection...;
...
public ... foobar(...) {
synchronized(lock) {
...
}
}
}
And, If I need to protect static members:
...
private static final Object lock = new Object();
...
The lock variable is private, just like the data it protects. Nobody who wants to understand your code will need to spend any time searching for anything else that is protected by the same lock object because they know it can't be accessed from outside of the MyClass methods.
The lock variable also is final. That will save readers from having to examine your code to make sure that it's always the same object that gets used as the lock. (Hint: if you think you need to be able to assign the lock variable, then you are either doing something that's sophisticated beyond the comfort level of many programmers, or you are making a bad mistake.)
I am trying to synchronize read write operations on XML file from multiple methods in multiple classes. To achieve this, I am synchronizing this operation by using class level lock.
That is not a good idea. You should have a single class (maybe XmlHelper) which manages the XML file and does the locking. XmlHelper would be used in the multiple methods in multiple classes and would control the locking on the file instead of multiple classes having to worry about it. That's much better object design.
Maybe something like:
public class XmlHelper {
public XmlHelper(File xmlFile) {
public synchronized SomeObject readSomething() { ... }
public synchronized void writeSomething(SomeObject someObject) { ... }
}
Then your Test1 and Test2 classes must share the same instance of the XmlHelper class so their locks will block each other. Instance level locks aren't always a great idea again because locks should be as fine-grained as possible, but it is fine in your application since the XmlHelper is designed for multiple classes to lock their IO operations.
What are the impacts of using Object.class instead of CommonUtility.class, like:
As others have mentioned, locking on the class is the same as calling a synchronized static method. This pattern should be used very sparingly since the lock is so coarse grained. What if your program needed to read/write to 2 XML files at the same time? Your class level lock would cause IO operations to the 2 files block each other -- not optimal.
If you locked on Object.class then any other class which happens to be doing the same lock will block your threads unnecessarily. God help you.
A race condition is getting hit. For example: thread1 reads file contents and updates read contents. Before thread1 writes back to file, thread2 reads content. Then thread1 writes updated contents to file. And at last thread2 writes content to file. This is leading to contents loss,
There are a couple of ways of doing this. You could have some sort of update method on your XmlHelper class:
public synchronized void updateObject(...) {
SomeObjecto obj = readSomething();
// adjust object here based on the arguments
writeSomething(obj);
}
If each of the threads need to do their own updating then they will need to lock externally on the same object. I recommend locking on the shared instance of the XmlHelper.
synchronized (xmlHelper) {
...
}
The locking on the class object will work but it is far to big a hammer to be recommended. Again, if you have 2 instances of the XmlHelper working on 2 different files, you would not want IO operations on 2 different files to block each other.

java synchronizedMap operations on map objects should be synchronized

my code uses the following:
public class Obj{
public String someOperation(){...}
};
public class ClassA{
private Map<Integer, Object> m_MsgHash;
public boolean init()
{
m_MsgHash = Collections.synchronizedMap(new LinkedHashMap<Integer, Object>(1001, 1.0F, true));
}
private Object fetchFromHash(int Id)
{
return m_MsgHash.get(Id);
}
public void HandleMsg(int Id)
{
Object obj = fetchFromHash(Id);
// do some operation on obj needs to be synchronized ?
//synchronized (m_MsgHash) {
obj.someOperation();
//}
}
}
I understand from Java Doc that once iterating the my m_MsgHash i must use the synchronized keyword. but my question is, do i need to use the synchronized when using a fetched Object from my map ?
You do not need "synchronized" for simple operations on a synchronizedMap result, such as get. If the object referenced by obj is itself accessed from multiple threads, and modified by at least one of them, you need to make all accesses to it synchronized on the same object, or otherwise ensure multi-thread correctness.
No you don't: m_MsgHash.get(Id); is synchronized so it is a thread safe operation. And once you have a reference to obj you can do whatever you want with it without needing to synchronize as it lives independently from the map (as long as you don't share it across threads, but here it is a local variable).
Note however that your map is not safely published as it is. If a thread calls init and another calls HandleMsg, it is possible that the second thread sees a null value for the map.
A simple way to safely publish the map would be to make it final and instantiate it within the constructor of ClassA.
Not required. Whenever you call Collections.synchronizedMap It creates a class that implements Map interface and has all the methods synchronized. This is called Java Monitor Pattern, where the underlying LinkedHashMap is protected by a Java Monitor to enable thread safety. You need to synchronize while looping because the Map may change while looping through.
But actions like put, get and remove are protected by the class Monitor thus not required to be inside of synchronized methods, unless they are part of a composite action such as Check-Then-Act.

Java concurrency confusion

I've following class
class A{
private int id =0;
public void setMessageId(Message m) {
synchronized(m) {
m.setId(id++);
}
}
}
Can two threads with same instance of class A with DIFFERENT instances of Message enter into the synchronized block at same time and set same id to different instances of message?
Yes. You need to synchronize on the object that holds the id field (in this case 'A') or some common object.
Yes. Since the block is synchronized on the message, two threads using two different message instances can enter the synchronized block concurrently, and both get the same ID.
Make the method synchronized, and everything will be fine. Or use an AtomicInteger.
If you only synchronize on m, then two objects will be able to modify the same instance of A. You need to synchronize on the object that stores the value id.
Sure, because you synchronize on different objects.
If all what you need for this purpose it's ID generation better to use java.util.concurrent AtomicInteger.
For example like this:
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
1. As the synchronized lock is on the instance of message, and then two thread with different message object can definately access this block at the same time.
2. Even if they are setting the same instance variable, its like a personal copy which is one per object.
3. Thread changing the variable id of one object will Not effect the id of other object.
Yes:
The lock object is obtained for the m object which are 2 different objects for each of your threads so yes they can. You will need to obtain a lock which is shared between those 2 and that A class in your case.
Yes, because they both have locks to different objects.
One option without self made synchronization at all is to use AtomicInteger:
class A{
private final AtomicInteger id = new AtomicInteger();
public void setMessageId(Message m) {
m.setId(id.incrementAndGet());
}
}
Method incrementAndGet incerements value by one and returns updated value.

Synchronization concerns with a static method in java

Suppose I have a Utility class,
public class Utility {
private Utility() {} //Don't worry, just doing this as guarantee.
public static int stringToInt(String s) {
return Integer.parseInt(s);
}
};
Now, suppose, in a multithreaded application, a thread calls, Utility.stringToInt() method and while the operation enters the method call, another thread calls the same method passing a different s.
What happens in this case? Does Java lock a static method?
There is no issue here. Each thread will use its own stack so there is no point of collision among different s. And Integer.parseInt() is thread safe as it only uses local variables.
Java does not lock a static method, unless you add the keyword synchronized.
Note that when you lock a static method, you grab the Mutex of the Class object the method is implemented under, so synchronizing on a static method will prevent other threads from entering any of the other "synchronized" static methods.
Now, in your example, you don't need to synchronize in this particular case. That is because parameters are passed by copy; so, multiple calls to the static method will result in multiple copies of the parameters, each in their own stack frame. Likewise, simultaneous calls to Integer.parseInt(s) will each create their own stack frame, with copies of s's value passed into the separate stack frames.
Now if Integer.parseInt(...) was implemented in a very bad way (it used static non-final members during a parseInt's execution; then there would be a large cause for concern. Fortunately, the implementers of the Java libraries are better programmers than that.
In the example you gave, there is no shared data between threads AND there is no data which is modified. (You would have to have both for there to be a threading issue)
You can write
public enum Utility {
; // no instances
public synchronized static int stringToInt(String s) {
// does something which needs to be synchronised.
}
}
this is effectively the same as
public enum Utility {
; // no instances
public static int stringToInt(String s) {
synchronized(Utility.class) {
// does something which needs to be synchronised.
}
}
}
however, it won't mark the method as synchronized for you and you don't need synchronisation unless you are accessing shared data which can be modified.
It should not unless specified explicitly. Further in this case, there wont be any thread safety issue since "s" is immutable and also local to the method.
You dont need synchronization here as the variable s is local.
You need to worry only if multiple threads share resources, for e.g. if s was static field, then you have to think about multi-threading.

What Cases Require Synchronized Method Access in Java?

In what cases is it necessary to synchronize access to instance members?
I understand that access to static members of a class always needs to be synchronized- because they are shared across all object instances of the class.
My question is when would I be incorrect if I do not synchronize instance members?
for example if my class is
public class MyClass {
private int instanceVar = 0;
public setInstanceVar()
{
instanceVar++;
}
public getInstanceVar()
{
return instanceVar;
}
}
in what cases (of usage of the class MyClass) would I need to have methods:
public synchronized setInstanceVar() and
public synchronized getInstanceVar() ?
Thanks in advance for your answers.
The synchronized modifier is really a bad idea and should be avoided at all costs. I think it is commendable that Sun tried to make locking a little easier to acheive, but synchronized just causes more trouble than it is worth.
The issue is that a synchronized method is actually just syntax sugar for getting the lock on this and holding it for the duration of the method. Thus, public synchronized void setInstanceVar() would be equivalent to something like this:
public void setInstanceVar() {
synchronized(this) {
instanceVar++;
}
}
This is bad for two reasons:
All synchronized methods within the same class use the exact same lock, which reduces throughput
Anyone can get access to the lock, including members of other classes.
There is nothing to prevent me from doing something like this in another class:
MyClass c = new MyClass();
synchronized(c) {
...
}
Within that synchronized block, I am holding the lock which is required by all synchronized methods within MyClass. This further reduces throughput and dramatically increases the chances of a deadlock.
A better approach is to have a dedicated lock object and to use the synchronized(...) block directly:
public class MyClass {
private int instanceVar;
private final Object lock = new Object(); // must be final!
public void setInstanceVar() {
synchronized(lock) {
instanceVar++;
}
}
}
Alternatively, you can use the java.util.concurrent.Lock interface and the java.util.concurrent.locks.ReentrantLock implementation to achieve basically the same result (in fact, it is the same on Java 6).
It depends on whether you want your class to be thread-safe. Most classes shouldn't be thread-safe (for simplicity) in which case you don't need synchronization. If you need it to be thread-safe, you should synchronize access or make the variable volatile. (It avoids other threads getting "stale" data.)
If you want to make this class thread safe I would declare instanceVar as volatile to make sure you get always the most updated value from memory and also I would make the setInstanceVar() synchronized because in the JVM an increment is not an atomic operation.
private volatile int instanceVar =0;
public synchronized setInstanceVar() { instanceVar++;
}
. Roughly, the answer is "it depends". Synchronizing your setter and getter here would only have the intended purpose of guaranteeing that multiple threads couldn't read variables between each others increment operations:
synchronized increment()
{
i++
}
synchronized get()
{
return i;
}
but that wouldn't really even work here, because to insure that your caller thread got the same value it incremented, you'd have to guarantee that you're atomically incrementing and then retrieving, which you're not doing here - i.e you'd have to do something like
synchronized int {
increment
return get()
}
Basically, synchronization is usefull for defining which operations need to be guaranteed to run threadsafe (inotherwords, you can't create a situation where a separate thread undermines your operation and makes your class behave illogically, or undermines what you expect the state of the data to be). It's actually a bigger topic than can be addressed here.
This book Java Concurrency in Practice is excellent, and certainly much more reliable than me.
To simply put it, you use synchronized when you have mutliple threads accessing the same method of the same instance which will change the state of the object/or application.
It is meant as a simple way to prevent race conditions between threads, and really you should only use it when you are planning on having concurrent threads accessing the same instance, such as a global object.
Now when you are reading the state of an instance of a object with concurrent threads, you may want to look into the the java.util.concurrent.locks.ReentrantReadWriteLock -- which in theory allows many threads to read at a time, but only one thread is allowed to write. So in the getter and setting method example that everyone seems to be giving, you could do the following:
public class MyClass{
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private int myValue = 0;
public void setValue(){
rwl.writeLock().lock();
myValue++;
rwl.writeLock().unlock();
}
public int getValue(){
rwl.readLock.lock();
int result = myValue;
rwl.readLock.unlock();
return result;
}
}
In Java, operations on ints are atomic so no, in this case you don't need to synchronize if all you're doing is 1 write and 1 read at a time.
If these were longs or doubles, you do need to synchronize because it's possible for part of the long/double to be updated, then have another thread read, then finally the other part of the long/double updated.

Categories