High-Level Concurrency in an Android Game Loop - java

I am trying to synchronize a pair of non-UI threads, one thread to run game logic and one thread to render, in order to execute tasks in a logical and efficient order. A constraint I imposed myself was that the entire system operate at an allocation-free steady state, so all display objects are returned and 'recycled' and therefore the two threads must maintain a sort of two-way dialog, which occurs when I call the 'swapBuffers()' method.
In pseudocode, the order of events in the game thread looks something like this:
while(condition)
{
processUserInput();
runGameLogicCycle(set number of times);
waitForBuffersSwapped();
unloadRecycleBuffer(); //This function modifies one buffer
loadDisplayBuffer(); ///This function modifies another buffer
waitForRenderFinished();
renderThread.postTask(swapBuffersAndRender);
}
The render thread is chosen to do the task of swapping buffers such that the game logic thread can do tasks in the meantime that do not modify the buffers. In my code, I combine the task of swapping buffers and rendering and define it as a Runnable object which is posted to the render thread's handler. In pseudocode, that runnable looks something like this:
{
//Swap the buffers
}
gameThread.notifyThatBuffersSwapped();
{
//Render items to screen
}
gameThread.notifyThatItemsRendered();
My problem is an implementation problem. I am familiar with the concepts of handlers, synchronization blocks, and ReentrantLocks. I am aware of the Lock.await() Lock.signal() methods, but I find the documentation insufficient when trying to understand how they behave when called in an iterating loop.
How does one implement ReentrantLocks to make two threads wait on each other in such a way? Please include a practical idiom in your answer if possible.

I'm not sure a Lock is what you want. You do want the current thread to have exclusive access to the objects, but once you release the lock you want to be sure the other thread gets to execute before you get the lock again.
You could, for example, use the poorly-named ConditionVariable:
loop:
game thread: does stuff w/objects
game thread: cv1.close()
game thread: cv2.open()
[render thread now "owns" the objects]
game thread: does stuff w/o objects
game thread: cv1.block()
game thread: [blocks]
loop:
render thread: does stuff w/objects
render thread: cv2.close()
render thread: cv1.open()
[game thread now "owns" the objects]
render thread: cv2.block()
render thread: [blocks]
This operates the two threads in lockstep. You get some concurrency when doing operations on non-shared objects, but that's it.
java.util.concurrent provides CountDownLatch, but that's a one-shot object, which goes against your desire to avoid allocations. The fancy CyclicBarrier does more.
This isn't a great solution -- while locks weren't exactly what you wanted, they were part of what you wanted, and I've done away with them here. It's not possible to look at the code and easily determine that both threads can't operate on the objects simultaneously.
You may want to consider double-buffering the objects. You'd need twice as much memory, but the synchronization issues are simpler: each thread essentially has its own set of data to work on, and the only time you have to pause is when the game thread wants to swap sets. Concurrency is maximized. If the game thread is late, the render thread just draws what it has again (if you're using a GLSurfaceView) or skips rendering. (You can get fancy and triple-buffer the whole thing to improve throughput, but that increases memory usage and latency.)

Related

how to use multiple threads, in sync?

i have multiple threads, who all run from one object.
i want the "main thread" to run alone until a certain point, then it waits and all the other threads run together, then the main thread wakes, etc.....
i am having trouble synchronizing my threads. i either get an Illegal Monitor State Exception, or it gets stuck in one of the "wait" loops that are suppose to receive a "notify" that never arrives.
more specifically, i have an object with an array. each cell in the array has a thread that checks the adjacent cells and then changes it's cell with that information.
in order to make the changes orderly, i want all the cells to first make the check of their adjacent cells and keep the value they produced, then wait.
when all of them are done, the main thread will wake all of them up and they will update their respective cells.
i looked up how "wait" and "notify" work, but i still don't understand how they sync. from what i understand i need to connect them all to one object, and then that object is the "lock", so if i use "synchronize" on its methods only one thread can approach it at a time? how can i make sure a "wait" method will always have a "notify" to end it?
Edit:
the method basically runs Conway's game of life.
the main orientation of the code is like so:
the class LifeMatrix extends JPanel. it had an array of panels, each is either "dead or alive" (true/false). the class RunMatrixThread extends thread, and is the "main thread" that coordinates the code. the class CellThead extends thread, and a CellThread is made for every cell in the matrix.
so my idea was to give all the threads the "LifeMatrix" as an observer, but if i try to notify the LifeMatrix Object (with matrix.notify()) it gives me the Illigal Monitor State Exception, and if i try to use "notify all" it gets stuck in RunMatrixThread's wait() command.
also, do i notify an object? or do i notify the threads that are waiting?
Don't use parallelization. Before using threads think if you really can parallelize your job because if all of your tasks have to be sync with each other use threads won't give you better perfomance in terms of execution time. Say that you have an array of objects [a,b] if a must waiting for some changes on b, you can't treat a and b separately so you can't parallelize your job. On the contrary if you need to process a, b and all the elements of your array and at the end perform some computation on them you can Join the threads with join() method. When you call join method you basically join threads branches in one (the main thread). A new thread will fork your main thread and join will join these threads.
If you're trying to get "worker threads" to do parcels of work that are authorized/initiated/doled-out by a "main" thread, then you probably should be using a thread pool (e.g, https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html)
A thread pool takes care of creating the worker threads and "synchronizing" their activity with the main thread, and it lets you focus on the task (or tasks) that the workers perform.
each cell in the array has a thread that...
For Conway's Life, that's way too many worker threads. If the work is purely compute-bound, then there's no point in having many more threads than your host has processors to execute them.
If I was coding life for a host with N processors, I would use a thread pool that had N threads. And, In each generation, I would have the main thread submit N tasks to the pool: Each task would do one horizontal stripe of the board.
Ok, first of all i want to thank all of you for trying to help, some of the links you gave me were very helpful.
I found out what my problem was: i was trying to use wait/notify methods from 2 different types of threads at the same time, on the same object. i had the 'CellThread' that used wait and 'notifyAll', and i had the 'RunMatrixThread' that did the same. they of course had "synchronized" methods, but because they were 2 different TYPES of threads, the two types weren't in sync with EACH OTHER.
what solved the problem was that i made 2 new synchronized methods within the 'RunMatrixThread' class, one for waiting and one for notifying, and then just called those methods from all threads (from both thread classes) whenever i wanted to wait/notify. in this way, there was a unified object that had a lock on everything.
PS: i know its a bad idea to use so many threads. it was the coarse's assignment, and they required we do it this way.

java Threads in libGDX

I am working on making a game with libGDX and I really want to thread the game so I am running a paint loop and a logic loop on separate threads much like you would making a simple java swing game with the paintcomponent loop and the runnable run loop.
I am experienced with threading in c but not so much in java.
The only way I was able to make a thread was by making a class that extends threads and then creating the run loop in there.
But the point of making the run loop was to allow each screen to compute logic freely, so I would end up needing some sort of abstractscreen class that has the custom thread class implemented.
I am asking if there is a simpler or more standard way of implementing threads for this situation.
The libGDX library already runs a separate render thread for the OpenGL context updates. See http://code.google.com/p/libgdx/wiki/TheArchitecture#The_Graphics_Module
We already learned that the UI thread is not executed continuously but only scheduled to run by the operating system if an event needs to be dispatched (roughly :p). That's why we instantiate a second thread we usually refer to as the rendering thread. This thread is created by the Graphics module that itself gets instantiated by the Application at startup.
The ApplicationListener.render() method on your main game object will be invoked by this render thread once for every screen refresh (so it should be about 60hz), so just put the body of your render loop in your implementation of this method.
You can create an additional background thread (e.g., for game logic) in the create method of your ApplicationListener (be sure to clean it up in the dispose method). Other than the render thread, I don't think any of the pre-existing threads would be the right place for game logic.
For communication between the threads, you can use any of the existing Java synchronization approaches. I've used Java's ArrayBlockingQueue<> to send requests to a background thread. And I've used Gdx.app.postRunnable() to get my background threads to push data to the render thread (such Runnables are run on the next frame, before render() is invoked).
Not sure what you mean, but it is standard that the drawing on the screen (reflect changes to the display) is done by a dedicated, single thread (e.g. see Swing framework). This is because it is quite difficult to let multiple threads draw on the screen without messing things up -- only few implementations do this. Hence, if you are planning to implement the GUI framework yourself, single threaded drawing approach would be recommendable.
As for your business logic, it depends on many things. A very simple approach could indeed to spawn a new thread for each activity. These threads can then post the result to the said GUI thread. The problem with this approach is that your efficiency can drop significantly if many activities are concurrently executed at the same time, because in Java, every thread maps to a native OS thread. You can use thread pools to avoid that. Java standard library provides thread pools as ThreadPoolExecutor or if you want a bit higher abstraction, ExecutorService.

How to synchronize shared data between threads by using pause then resume or alternatives

I'm writing a game in which a thread - GameThread - loops forever, updating all my sprites, rendering them, and then sleeping for some time before doing it all again. I also have a custom-made Event handler which deals with key presses etc.
This all works fine in most cases. However I have a problem if an event is thrown while GameThread is rendering. On rare occasions, the handler that deals with the event may make a concurrent change to what needs to be rendered affecting the results of the GameThread rendering.
To avoid this, I want the event handler to pause the GameThread immediately, handle the event, then resume GameThread.
The suspend() / resume() methods suit my needs, but they were deprecated. In my case, however, as there is little chance of a deadlock, is it safe to use them regardless?
If no, what other alternatives do I have that don't have a huge amount of overhead?
I have seen a suggestion of requesting a thread to pause by setting a flag in the Thread to be paused. In my case, however, I don't see that as a viable option since the GameThread loop may take a while during an iteration through the loop. I won't be able to check the flag until I'm done with the loop and by then it is too late.
I need immediate pausing, or else the user will notice a delay in the event handling.
If you want to synchronize access to resources, use a ReentrantLock:
ReentrantLock sync = new ReentrantLock();
You'd have to pass that lock to each runnable where you want to access the shared data.
Then in each place you're accessing the resource in question, you would use that shared lock object, and obtain and release the lock (ie, your critical sections):
sync.lock();
try {
// critical section code here
}
finally {
sync.unlock();
}
This is pretty standard concurrent programming in java. Keep in mind "lock" is a blocking method, so you might want to use "tryLock" instead, which allows you to try and acquire the lock, but returns a boolean as to whether or not you actually got the lock:
if (sync.tryLock()) {
try {
//critical section
}
finally {
sync.unlock();
}
}
There's a version of "tryLock" which will wait a given amount of time, before it will give up trying to acquire the lock and return a false value.
Usually, you would do some thread synchronization:
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
This would let you do one of the two things you are doing: either render in the game rendering thread or do the changes based on your events.
The problem you are facing seems to be that your rendering code is taking too long for you to actually have a smooth experience (i.e. a lot of events can pile up for processing while you are rendering something). In that case, you should make your rendering out of independent pieces that can finish quickly and synchronize on them.
Without any code I cannot give you a specific advice, however in general it would look something like this:
List<Shape> shapesToRender;
Object lockObject = new Object(); // Note this must be somehow shared between two threads
// Your rendering thread method
public void renderForever() {
while(true) {
for(Shape shape: shapesToRender) {
synchronized(lockObject) {
render(shape);
}
}
}
}
// One of your event handlers
public void handleEvent(Event event) {
synchronized(lockObject) {
// Process event somehow, e.g. change the color of some of the shapes
event.getShape().setColor(Color.RED);
}
}
With the above, either:
You will be rendering one shape (and all your event handlers will be waiting for that to finish), or
Some of your event handlers will be doing something (and your rendering thread will be waiting for that to finish)
You should look at this Java trail in more depth:
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
as there are other solutions, e.g. using lock objects:
http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html
or concurrent collections:
http://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html
that, depending on your problem, might be easier and, most importantly, very well tested solutions that would allow you to do something in a standard way, thus avoiding all the pitfalls that you can get into when rolling out custom threading code.
Hope this helps.
The suspend() / resume() methods suit my needs, but they were deprecated. In my case, however, as there is little chance of a deadlock, is it safe to use them regardless?
Obviously, if there is ZERO chance of a deadlock then it is safe. But there are all sorts of unexpected ways to get a deadlock. For instance, you could happen to pause a thread while it is initializing a class ... and that would deadlock any other thread trying to refer to a static field of that class. (This is a consequence of a specified behaviour of the JVM. There are other places where the locking / synchronization that goes on under the hood is not specified. Fair enough. It doesn't need to be ... unless you are contemplating using these deprecated methods.)
So, the reality is that it is really difficult to determine (prove) if it is actually safe. And if you can't determine this, then it is a potentially risky thing to do. That's WHY the methods are deprecated.
(Strictly speaking, this is not a deadlock. A deadlock is when the threads can never proceed. In this case, the other threads can proceed if you can resume the paused thread.)

Java Swing application: how to get data from the GUI thread to another thread?

In my Java application with a Swing GUI, I would like to achieve the following.
There is a non-GUI thread running, performing some work. At one point, this thread needs input from the user before it can continue. Then, I would like to make some changes to the GUI, await a specific GUI action (like the user pressing the OK button), get the entered data from the GUI to the non-GUI thread, and let it continue with the computation.
Looking around, I have found a lot of information about how to initiate the execution of a (long running) task from the Swing GUI thread on another thread, but nothing on my problem.
SwingUtilites.invokeAndWait sounds like it does the job, but first, it takes a Runnable argument instead of a Callable, so there is no straightforward way to return a result, and second, it does not solve the problem of waiting for a certain GUI event.
I realize I could make up my own solution using e.g. a CountDownLatch, but to me, the problem seems frequent enough for there to be a standard solution.
So, my questions are: Is this really a frequent problem, and if yes, is there a solution in the standard library / libraries? If there is no standard solution, how would you solve it? If this problem doesn't occur often, why not?
Kicking off the GUI changes is easy, so I assume you're only asking about getting data back to the worker thread.
First, create a Blocking Queue. Have the worker thread call take() on the queue, and it will block. In GUI space, once the user enters valid input, put it on the queue with offer() and the worker thread will receive the data and can continue.
I think, you can use ExecutorService where you can also track progress of your task through Future interface.
java.awt.EventQueue.invokeLater works nicely for running code on the AWT EDT. Propbably best to copy mutable data or better use immutable data. Locks are possible, but a bit dicey.
If you other thread is an event dispatch loop, you could implement something like invokeLater for your thread (but don't make it static!). Probably use it behind some interface that makes sense to the behaviour of the thread - so it's real operations rather than run which is specified as doing anything it pleases. If your thread is going to block, then a BlockQueue is fine, but don't block from the AWT EDT.
java.awt.EventQueue.invokeAndWait is like using a lock. Probably you are going to use another lock. Or perhaps a lock like invokeAndWait on you own thread. If you don't, AWT uses a lock anyway. So, uncontrolled nested locks, that probably means deadlock. Don't use invokeAndWait!
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
//Runnable method implementation.
//use result in your method like local var.
});
Make sure that your shared data is synchronized use lock objects.
If you need to pass arguments to Runnable just make your local variables final,
and use them in run method.

Multithreading in a networked swing game: using invokeLater vs locks

I am writing a simple top down space game, and am extending it to allow play over a network with multiple players. I've done a fair bit of reading, but this is the first time I've done this and I'd appreciate some advice on choosing a sensible design.
My GUI is written using Swing. 30 times a second, a timer fires, and repaints my GUI according to data in a gameWorld object in memory (essentially a list of ships & projectiles with positions, etc). Physics updates of the gameWorld are also carried out using this timer. Thus, for the single player implementation, everything happens on the EDT, and this works fine.
Now, I have separate thread dealing with incoming packets from other players. I would like to update the data in my gameWorld object based on what these packets contain. My question is, should I use invokeLater to make these changes, or should I use locks to avoid concurrency problems?
To illustrate what I mean:
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameWorld.updateWithNewGameInfo(data);
}
});
}
}
vs
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
synchronize (gameWorldLock) {
gameWorld.updateWithNewGameInfo(data);
}
}
}
The latter would also require using similar synchronize blocks wherever the EDT accesses the gameWorld, so it seems to me that using invokeLater would be simpler to implement. But am I right in thinking both approaches would work? Are there any other significant pros/cons to bear in mind?
Thanks,
Jeremy
Well, first of all you don not need to choose only one method. You can use locks to make you data structure thread-safe "just to be sure" (since your application is already multithreaded), and use invokeLater to actually apply changes only in EDT -- and in this case JIT likely to optimize you locks down, close to 0.
Next, from my point of view invokeLater is rather preferred way: if you can way around dealing with multi-threaded -- you should use the way, just because multithreading is hard and rich of possible errors.
But applying changes via invokeLater() will put additional pressure on EDT, so, if changes come with high rate you can observe GUI degradation. Also, if gameWorld.updateWithNewGameInfo(data) is havy method taking observable time to complete, it can makes you GUI even freeze. Also, invokeLater puts your task at the tail of event queue, so it'll be done after all events currently in queue. It may -- in some cases -- cause delays in applying changes, which can makes you game less user-friendly. It may, or may not be your case, but you'll should keep it in mind
As for general rule -- not use EDT for any time consuming task. As far, as I understand, network packet parsing is already in seperate thread in your application. Applying changes can (and should) be done in separate thread too, if it is time consuming.
Pros for approach 1:
Minimized complexity
Stability
By restricting access to the 'gameWorld' variable to the EDT thread, locking mechanisms are not required. Concurrent programming is complex and requires the programmer(s) to be vigilant throughout the source base when accessing objects shared amongst threads. It is possible for
a programmer to forget to synchronize in certain instances, leading to compromised game states or program failure.
Pros for approach 2:
Scalability
Performance
Minimizing the processing done on the EDT thread ensures that the games interface and display will remain responsive to the user. Approach 1 may work for now, but later revisions of your game will not be able to scale to a more advanced interface if the EDT thread is busy doing non-ui processing.
Not the second one. You want to have as little as possible running in the EDT. If you are waiting for a lock in the EDT, it's as bad as running all the other code (on the other side of the lock) directly in the EDT since the EDT has to wait for everything else to finish.
Also, it seems that your whole game is running on the EDT. That's bad practice. You should split your code using the model-view-controller pattern. I understand your game is small and can run in the EDT, but you should probably not get into the habit.
You should have your game logic running from a timer thread (java.util.concurrent.ScheduledThreadPoolExecutor) and at the end of every period you "send" your data to the EDT and repaint with invokeLater.
You should also have some separate thread that reads the socket and that thread should write to objects that share locks with the objects you are using in the timer game thread.
My suggestion is as follows
push all loaded data from different users (thread) to a queue
use another thread to read from that queue and update UI from EDT
It should avoid your concurrency issue. How it can be achived
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
blockingQueue.add(data);
}
}
runMethodOfUPdateUIThread() {
while(updatingUI) {
data = blockingQueue.take();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameWorld.updateWithNewGameInfo(data);
}
});
}
}

Categories