Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (523)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (591)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Thread & Semaphors  (Read 5246 times)
0 Members and 1 Guest are viewing this topic.
Offline darcone

Junior Devvie




Size matters


« Posted 2003-11-07 12:20:44 »

I am wondering if there is any class to do this, or perhaps a way to Lock a Object by a specific thread (I see there is a method holdsLock(Object obj) that checks if an object is locked by a thread, how do you lock it??) Any help appreciated.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #1 - Posted 2003-11-07 12:32:09 »

Read the Java docs on multi-threading.  Object.wait(), Object.notify() are the APIs you want, along with the synchronize keyword.

Offline AndersDahlberg

Junior Devvie





« Reply #2 - Posted 2003-11-07 12:44:01 »

Check out the "new" 1.5 (well not really new) concurrent package (jsr-166), there you can find a lot information about threading + java. Great stuff! Grin

http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jeff

JGO Coder




Got any cats?


« Reply #3 - Posted 2003-11-07 18:46:45 »

But if all he wants is a mutex/semaphore he doiesn't need all the new 1.5 stuff.

In Java EVERY object has a Mutext inherently associated with it.

(As others have said see Object.wait() and Object.notify()  Wink )

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline darcone

Junior Devvie




Size matters


« Reply #4 - Posted 2003-11-09 13:09:57 »

Alright.. My problem is that a HashMap isn´t synchronized... And I don´t really get the javadoc of hashMap it tells me to wrap it in some way, but wrapping it in a List class doesn´t make sense.. Someone done this before?

There is the code that I want to use a mutex with:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
    private synchronized void loopWriteQeue() {

        while(!writeQeueAvailable) {
           
            try { writeQeue.wait(); }
            catch(Exception e) { }
        }
       
        writeQeueAvailable = false;
       
        for(Iterator i = writeQeue.keySet().iterator() ; i.hasNext();) {

            SpeedChannel key = ((SpeedChannel)i.next());

            try { ((SpeedChannel)(writeQeue.get(key))).write(); }
            catch(Exception e) { }

            if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
        }
       
        writeQeueAvailable = true;
        writeQeue.notify();
    }
   
    protected synchronized void addToWriteQeue(SpeedChannel add) {
       
        while(!writeQeueAvailable) {
           
            try { writeQeue.wait(); }
            catch(Exception e) { }
        }
       
        writeQeueAvailable = false;
       
        writeQeue.put(add, add);
       
        writeQeueAvailable = true;
        writeQeue.notify();
    }
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #5 - Posted 2003-11-09 14:39:54 »

The solution is right there in the docs:

1  
Map m = Collections.synchronizedMap(new HashMap(...));


But seriously read the Java docs about synchronization, it may be that simply wrapping the map has too fine a granualrity.  I find that most of the synchronized collections in the Java API are useless because the synchronization only protects the data structure itself from corruption, but does not protect your algorithm that uses it from corruption.

Offline tom
« Reply #6 - Posted 2003-11-09 14:55:01 »

From Collections.synchronizedMap(Map m) javadoc:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views: 

  Map m = Collections.synchronizedMap(new HashMap());
      ...
  Set s = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized(m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }


So you would have to synchronize on the synchronized Map when you iterated over the queue.

Offline tom
« Reply #7 - Posted 2003-11-09 15:00:38 »

If you would like to synchronize the queue yourself, this is what the code might look like:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
private void loopWriteQeue() {  
 synchronized(writeQueue) {
  for(Iterator i = writeQeue.keySet().iterator() ; i.hasNext();) {
   SpeedChannel key = ((SpeedChannel)i.next());
   try { ((SpeedChannel)(writeQeue.get(key))).write(); }
   catch(Exception e) { }
   if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
  }
 }
}

protected void addToWriteQeue(SpeedChannel add) {
 synchronized(writeQueue) {
   writeQeue.put(add, add);
 }
}


It basicly means that only on block of code that is synchronized on the queue is allowed to run at any one time.

Offline darcone

Junior Devvie




Size matters


« Reply #8 - Posted 2003-11-09 20:07:24 »

Ok guys thanks a whole bunch I think that should solve it! Lets see *opens up netbeans* Smiley
Offline darcone

Junior Devvie




Size matters


« Reply #9 - Posted 2003-11-09 21:11:06 »

I did what you said (and I understood why I did this) but I still get that damn exception. Could someone explain why? Or give me a hint?

The code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
private void loopWriteQeue() {
       
        Map m = Collections.synchronizedMap(writeQeue);
        Set s = m.keySet();
       
        synchronized(m) {

            Iterator i = s.iterator();
           
            while(i.hasNext()) {
           
                SpeedChannel key = ((SpeedChannel)i.next());

                try { ((SpeedChannel)(writeQeue.get(key))).write(); }
                catch(Exception e) { }

                if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
            }
        }
    }
   
    protected void addToWriteQeue(SpeedChannel add) {

        Map m = Collections.synchronizedMap(writeQeue);
       
        synchronized(m) {
            writeQeue.put(add, add);
        }
    }
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline cfmdobbie

Senior Devvie


Medals: 1


Who, me?


« Reply #10 - Posted 2003-11-09 21:30:23 »

What exception are you getting?

As each method is obtaining a synchronised Map object individually, they are each getting a different synchronised view of the data.  Thus the internal synchronisation to maintain valid state, and the external synchronisation to maintain "transactional" state will be irrelevant.  What you want to do is create a shared Map reference (probably a private member variable) that points to the synchronised map, then in each of the methods synchronise on it before calling any of its methods.

Alternatively, if those two methods are the only places where that collection is used, you can forget about getting a synchronised map and just define those two methods as "synchronized".  But that's what your example code did - wasn't that working?

Hellomynameis Charlie Dobbie.
Offline darcone

Junior Devvie




Size matters


« Reply #11 - Posted 2003-11-09 21:53:00 »

I get a concurrency exception on the i.next() method. And yes Ive tried all the ways you described there. I even tried to synchronize on the THIS reference. It seems that it doesnt matter what I synchronize on it will still give me the exception. Here is the full exception:

1  
2  
3  
4  
5  
java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
        at java.util.HashMap$KeyIterator.next(Unknown Source)
        at SpeedConn.SpeedConn.loopWriteQeue(SpeedConn.java:97)
        at SpeedConn.SpeedConn.run(SpeedConn.java:47)
Offline cfmdobbie

Senior Devvie


Medals: 1


Who, me?


« Reply #12 - Posted 2003-11-09 22:17:34 »

If you're getting that, then your synchronisation must be broken somewhere.  Make sure that all code using the data is both accessing it via the synchronised reference and passing that reference when entering the synchronized block.  Make sure these restrictions will hold for all uses of the data, across different methods, different classes and different threads.

Something somewhere isn't playing by the rules!

Hellomynameis Charlie Dobbie.
Offline darcone

Junior Devvie




Size matters


« Reply #13 - Posted 2003-11-10 00:41:26 »

Thats the weird part, I dont touch it anywhere else :/
Any other ideas or should I just paste the two classes in here?
Offline Jeff

JGO Coder




Got any cats?


« Reply #14 - Posted 2003-11-10 02:28:35 »

Quote
Thats the weird part, I dont touch it anywhere else :/


Then likely this routine is being run from two different threads simultaneously.

Remember, Threads != routines.



Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline darcone

Junior Devvie




Size matters


« Reply #15 - Posted 2003-11-10 09:47:43 »

I thaught that was what I was trying to stop with synchronization? And my debug shows me that loopWriteQeue and addToWriteQeue are being run at the same time thats why the exception happens.
Offline tom
« Reply #16 - Posted 2003-11-10 10:14:34 »

You still get the exception after following cfmdobbie's advise? How do your functions look like now?

Offline darcone

Junior Devvie




Size matters


« Reply #17 - Posted 2003-11-10 10:22:30 »

Yeah, I created a private Map m; and use that in the synchronization. Here is how it looks like in the methods:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
private void loopWriteQeue() {
       
        m = Collections.synchronizedMap(writeQeue);
        Set s = m.keySet();
       
        synchronized(m) {

            Iterator i = s.iterator();
           
            while(i.hasNext()) {
           
                SpeedChannel key = ((SpeedChannel)i.next());

                try { ((SpeedChannel)(writeQeue.get(key))).write(); }
                catch(Exception e) { }

                if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
            }
        }
    }
   
    protected void addToWriteQeue(SpeedChannel add) {

        m = Collections.synchronizedMap(writeQeue);
       
        synchronized(m) {
            writeQeue.put(add, add);
        }
    }
Offline tom
« Reply #18 - Posted 2003-11-10 10:58:23 »

You must synchronize on the same object!

The line "m = Collections.synchronizedMap(writeQeue);" will create a new Map object everytime one of your functions are called. It must instead be called only once, preferably when you create writeQueue. Also, after the object m is called, you never, ever use "writeQueue"!!!!! Always use "m" instead.

You only need to synchronize on m, by useing synchronized(m) {...}, when you are using an iterator. In other words: when you are accessing the map by not using the maps member functions.

Here is how the changes will affect your code. Note that you will have to add a line to you constructor and remove the referance to writeQueue. This is done to make sure you do not use writeQueue.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
// constructor
public Queue() {
 // do not keep a referance to the unsynchronized map!!
 m = Collections.synchronizedMap(new HashMap());
}

private void loopWriteQeue() {
 Set s = m.keySet();
 synchronized(m) {  
 Iterator i = s.iterator();    
 while(i.hasNext()) {    
  SpeedChannel key = ((SpeedChannel)i.next());  
  try { ((SpeedChannel)(writeQeue.get(key))).write(); }
  catch(Exception e) { }  
  if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
  }
 }
}
     
protected void addToWriteQeue(SpeedChannel add) {
 // m will synchronize the put function by itself.
 writeQeue.put(add, add);
}


Also go over your code againg and make sure that you don't acces the "m" from any other place. Make it private and don't return it from any functions in any way.

Offline darcone

Junior Devvie




Size matters


« Reply #19 - Posted 2003-11-10 11:18:41 »

So you mean that if I make m = Collections.synchronizedMap(writeQeue); m will always have the same content as writeQeue? PErhaps that is what I have missed.

Here is the code now:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
private void loopWriteQeue() {

        Set s = m.keySet();
       
        synchronized(m) {

            Iterator i = s.iterator();
           
            while(i.hasNext()) {
           
                SpeedChannel key = ((SpeedChannel)i.next());

                try { ((SpeedChannel)(writeQeue.get(key))).write(); }
                catch(Exception e) { }

                if(!((SpeedChannel)writeQeue.get(key)).wantsToWrite()) writeQeue.remove(key);
            }
        }
    }
   
    protected void addToWriteQeue(SpeedChannel add) {

        writeQeue.put(add, add);
    }


And I still get the exception at the same place
Offline tom
« Reply #20 - Posted 2003-11-10 11:19:35 »

Here are some links about threads and synchronization:
Using Threads in J2ME Applications:http://wireless.java.sun.com/midp/articles/threading2/
The Java(tm) FAQ -- Threads:http://java.sun.com/docs/books/faq/faqthr.html

There are several books on the subject. Go to amazon and search for java treads.

Offline tom
« Reply #21 - Posted 2003-11-10 11:34:35 »

Quote
So you mean that if I make m = Collections.synchronizedMap(writeQeue); m will always have the same content as writeQeue?

Kind of. m is an interface to your original writeQueue object. It do not store any data in itself. It has a referance to your writeQueue and it calls the respective function on your writeQueue. In addition it makes sure that only one thread is allowed to use writeQueue at a time, using this interface object.

Offline darcone

Junior Devvie




Size matters


« Reply #22 - Posted 2003-11-10 13:52:59 »

So all methods I would call on writeQeue I should call on m now? like .get() and .put() ?
Offline tom
« Reply #23 - Posted 2003-11-10 14:49:08 »

yes

Offline darcone

Junior Devvie




Size matters


« Reply #24 - Posted 2003-11-10 16:18:28 »

ok thanks Ill work on it Smiley
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #25 - Posted 2003-11-11 00:34:33 »

You can't do this in the loop, it modifies the collection you are iterating over.. think about it.. connect the dots...

1  
writeQeue.remove(key); 



Make a COPY of the keys.. iterate over the copy...  Or (better) make a new collection of the objects you intend to remove, then remove them in a separate loop after you have all of them.

Offline darcone

Junior Devvie




Size matters


« Reply #26 - Posted 2003-11-11 06:30:48 »

Yeah I noticed this as well, but wasnt really sure Smiley Thanks!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Gibbo3771 (10 views)
2014-11-24 19:59:16

trollwarrior1 (35 views)
2014-11-22 12:13:56

xFryIx (73 views)
2014-11-13 12:34:49

digdugdiggy (52 views)
2014-11-12 21:11:50

digdugdiggy (46 views)
2014-11-12 21:10:15

digdugdiggy (40 views)
2014-11-12 21:09:33

kovacsa (66 views)
2014-11-07 19:57:14

TehJavaDev (70 views)
2014-11-03 22:04:50

BurntPizza (68 views)
2014-11-03 18:54:52

moogie (83 views)
2014-11-03 06:22:04
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!