java - sharing data between threads - atomicreference or synchronize - java

I am making a 2 player videogame, and the oponent's position gets updated on a thread, because it has a socket that is continuously listening. What I want to share is position and rotation.
As it is a videogame I don't want the main thread to be blocked (or be just the minimum time possible) and I don't want the performance to be affected. So from what I've seen to share this info the normal thing to do would be something like
class sharedinfo
{
public synchronized read();
public synchronized write();
}
but this would block the read in the main thread (the same that draws the videogame) until the three values (or even more info in the future are written) are written, and also I've read that synchronized is very expensive (also it is important to say this game is for android also, so performance is very important).
But I was thinking that maybe having sharedInfo inside an AtomicReference and eliminating synchronized would make it more efficient, because it would only stop when the reference itself is being updated (the write would not exist, I would create a new object and put it on the atomicreference), also they say that atomic* use hardware operations and are more efficient than synchronized.
What do you think?

Consider using a queue for this, Java has some nice concurrent queue implementations. Look up the BlockingQueue interface in java.util.concurrent, and who implements it. Chances are you fill find strategies implemented that you hadn't even considered.
Before you know it, you will want to communicate more than just positions between your threads, and with a queue you can stick different type of objects in there, maybe at different priorities, etc.
If in your code you use Interfaces (like Queue or BlockingQueue) as much as possible (i.e. anywhere but the place where the specific instance is constructed), it is really easy to swap out what exact type of Queue you are using, if you need different functionality, or just want to play around.

Related

In Android when should I use a lock and when should I use synchronized? Is there a difference?

I have an ArrayList which I add items to, within a broadcastreceiver callback.
However the arraylist will eventually be attached to an adapter and then I wish to display the contents of the array to the screen.
The array contains peer information from a P2P app I'm working on so it will be subject to change frequently as devices drop in and out of connection/range.
So basically the arraylist will be read and written to frequently.
I come from a c++ background so I would normally use a lock to protect my arraylist, when accessing it, but I'm unsure what I should use in java/android.
Any Advice please.
Using a lock is never wrong. All synchronized does is use a lock under the hood. Some Java purists may complain, but you tend to get more flexibility out of just using a semaphore (and sometimes its just the only way to be correct). There's also some ugly corner cases to wait/notify that you have to really understand the use cases of to get right that semaphores just avoid. If you're familiar with them I wouldn't hesitate to use it just because you're in Java now.
Use a BlockingQueue instead of an ArrayList. It'll make your list Thread safe. As per the Documenatation :
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
The synchronized keyword locks on whatever object is specified. If the method is marked as synchronized and its an instance method it locks on the enclosing instance. If the method is static, it locks on the class object. If an object is specified in parentheses after the synchronized keyword in a syncrhonized block, the lock is held on that object. I would typically use a thread safe collection like AndroidWarrior proposed, but if thats not possible, just make sure that your accessors and mutators lock on the same object.

Thread safety when only one thread is writing

I know if two threads are writing to the same place I need to make sure they do it in a safe way and cause no problems but what if just one thread reads and does all the writing while another just reads.
In my case I'm using a thread in a small game for the 1st time to keep the updating apart from the rendering. The class that does all the rendering will never write to anything it reads, so I am not sure anymore if I need handle every read and write for everything they both share.
I will take the right steps to make sure the renderer does not try to read anything that is not there anymore but when calling things like the player and entity's getters should I be treating them in the same way? or would setting the values like x, y cords and Booleans like "alive" to volatile do the trick?
My understanding has become very murky on this and could do with some enlightening
Edit: The shared data will be anything that needs to be drawn and moved and stored in lists of objects.
For example the player and other entity's;
With the given information it is not possible to exactly specify a solution, but it is clear that you need some kind of method to synchronize between the threads. The issue is that as long as the write operations are not atomic that you could be reading data at the moment that it is being updates. This means that you for instance get an old y-coordinate with a new x-coordinate.
Basically you only do not need to worry about synchronization if both threads are only reading the information or - even better - if all the data structures are immutable (so both threads can not modify the objects). The best way to proceed is to think about which operations need to be atomic first, and then create a solution to make the operations atomic.
Don't forget: get it working, get it right, get it optimized (in that order).
You could have problems in this case if list's sizes are variable and you don't synchronize the access to them, consider this:
read-only thread reads mySharedList size and it sees it is 15; at that moment its CPU time finishes and read-write thread is given the CPU
read-write thread deletes an element from the list, now its size is 14.
read-only thread is again granted CPU time, it tries to read the last element using the (now obsolete) size it read before being interrupted, you'll have an Exception.

Thread safe queue in Java

I want to implement a queue, that is hit by multiple threads.
This is stack is in a singleton class.
Now, a simple solution is to synchronize this? I assume it would need this as standard?
However, I want to prioritize writing to it.
So, write is high priority, read is low priority.
Is this possible?
Ideally writing by multiple threads without synchronizing would be great, if possible.
Why do you want to avoid synchronizing? It's possible to write "lock-free" structures, but it's quite tricky and easy to get wrong.
If I were you, I'd use ArrayBlockingQueue or ConcurrentLinkedQueue (or one of the other structures from java.util.concurrent) and make your life easy!
Oh, and I missed the bit about prioritising reads over writes. You can do that with the ReentrantReadWriteLock class. Then you don't need a thread-safe queue - you just lock externally using the read-write lock depending on whether you're reading or writing.

Inter-threads communication

The easiest implementation is when we call from single class main method other classes implementing runnable:
public static void main(String [] args){
// declarations ...
receiver.start();
player.start();
}
Say inside receiver I have while loop which receives a packet value and I want to send that value to the second thread. How to do that?
Just to clarify I don't yet care about one thread controlling another, I just want first thread to share values with second.
And tiny question aside - does JDK 7 Fork really dramatically increases performance for java concurrent api?
Thank You For Your Time,
A simple option is to use a java.util.concurrent.atomic.AtomicReference (or one of the other Atomic... classes). Create a single instance of AtomicReference, and pass it to the code that the various threads run, and set the value from the receiver thread. The other thread(s) can then read the value at their leisure, in a thread-safe manner.
does JDK 7 Fork really dramatically increases performance for java concurrent api?
No, it's just a new API to make some things easier. It's not there to make things faster.
The java.util.concurrent -package contains many helpful interfaces and classes for safely communicating between threads. I'm not sure I understand your use-case here, but if your player (producer) is supposed to pass tasks to the receiver (consumer), you could for example use a BlockingQueue -implementation.

Java: Large collection and concurrent threads

I am facing this issue:
I have lots of threads (1024) who access one large collection - Vector.
Question:
is it possible to do something about it which would allow me to do concurrent actions on it without having to synchronize everything (since that takes time)? What I mean, is something like Mysql database works, you don't have to worry about synchronizing and thread-safe issues. Is there some collection alike that in Java? Thanks
Vector is a very old Java class - predates the Collections API. It synchronizes on every operation, so you're not going to have any luck trying to speed it up.
You should consider reworking your code to use something like ConcurrentHashMap or a LinkedBlockingQueue, which are highly optimized for concurrent access.
Failing that, you mention that you'd like performance and access semantics similar to a database - why not use a dedicated database or a message queue? They are likely to implement it better than you ever will, and it's less code for you to write!
[edit] Given your comment:
all what thread does is adding elements to vector
(only if num of elements in vector = 0) &
removing elements from vector. (if vector size > 0)
it sounds very much like you should be using something much more like a queue than a list! A bounded queue with size 1 will give you these semantics - although I'd question why you can't add elements if there is already something there. When you've got thousands of threads this seems like a very inefficient design.
Well first off, this design doesn't sound right. It sounds like you need to think about using a proper database rather than an simple data structure, even if this means just using something like an in-memory instance of HypersonicDB.
However, if you insist on doing things this way, then the java.util.concurrent package has a number of highly concurrent, non-locking data structures. One of them might suit your purpose (e.g. ConcurrentHashMap, if you can use a Map rather than a List)
Looks like you are implementing the producer consumer pattern, you should google "producer consumer java" or have a look at the BlockingQueue interface
I agree with skaffman about looking at java.util.concurrent.
ConcurrentHashMap is very scalable. However, the size() call on it returns only an approximation. So e.g. your app will occasionally be adding elements to it even if !(num of elements in vector = 0).
If you want to strictly enforce the condition you gave, there is no other way than to synchronize.
Instead of having tons of context switches, I guess you could let your users thread post a callable on a queue and have only one thread dealing with the mutation. This will eliminate the need for synchronization on the collection. The user threads can wait on Future.get().
Just an idea.
If you do not want to change your data structure and have only infrequent writes, you might also use one or many ReentrantReadWriteLock to synchronize access. Then many threads can read at the same time, but when a thread wants to write all reads are blocked until the write is done.
But you should check whether the used data structure is appropriate for the task, or whether another of the many java.util or java.util.concurrent classes is more appropriate. java.util.Vector is synchronized, by the way.

Categories