'lo allemaal 
Ik ben momenteel bezig met het maken van een serverapplicatie waarin meerdere threads gebruik maken van data uit een object. Om concurrency problemen te voorkomen wordt de code welke toegang tot de data wil hebben in een synchronized blok gezet.
Like so:
Als test heb ik een set clients verbonden met de server, waarvan een paar de server zwaar gaan spammen met berichten. Als ik, terwijl er gespamt wordt (en broadcastToUsers dus hard bezig is met het verwerken van de opdrachten) een client laat disconnecten (waardoor removeUser wordt aangeroepen) dan geeft broadcastToUsers een ConcurrentModificationException.
Op zich is dat logisch als de users HashMap door meerdere processen wordt gebruikt/veranderd, maar dit zou dus niet moeten kunnen vanwege het gebruik van synchronized. Het lijkt erop dat tijdens het doorlopen van de users in broadcastToUsers er toch een proces toegang tot removeUser heeft gekregen, terwijl er op het object Users een lock zit.
Heeft iemand een idee hoe dit mogelijk is?
Ik ben momenteel bezig met het maken van een serverapplicatie waarin meerdere threads gebruik maken van data uit een object. Om concurrency problemen te voorkomen wordt de code welke toegang tot de data wil hebben in een synchronized blok gezet.
Like so:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| public class Data
private HashMap users = new HashMap();
[..]
public synchronized User getUser(String id)
{
synchronized(this.users)
{
if (this.users.containsKey(id))
{
return (User) this.users.get(id);
}
else
{
return null;
}
}
}
public synchronized void removeUser(String id)
{
synchronized(this.users)
{
if (this.users.containsKey(id))
{
this.users.remove(id);
}
}
}
public synchronized void broadcastToUsers(String message)
{
synchronized(this.users)
{
Set keySet = this.users.keySet();
Iterator keySetIterator = keySet.iterator();
while( keySetIterator.hasNext() )
{
String currKey = (String)keySetIterator.next();
User currUser= (User)this.users.get( currKey );
currUser.sendMessage( message );
}
}
} |
Als test heb ik een set clients verbonden met de server, waarvan een paar de server zwaar gaan spammen met berichten. Als ik, terwijl er gespamt wordt (en broadcastToUsers dus hard bezig is met het verwerken van de opdrachten) een client laat disconnecten (waardoor removeUser wordt aangeroepen) dan geeft broadcastToUsers een ConcurrentModificationException.
Op zich is dat logisch als de users HashMap door meerdere processen wordt gebruikt/veranderd, maar dit zou dus niet moeten kunnen vanwege het gebruik van synchronized. Het lijkt erop dat tijdens het doorlopen van de users in broadcastToUsers er toch een proces toegang tot removeUser heeft gekregen, terwijl er op het object Users een lock zit.
Heeft iemand een idee hoe dit mogelijk is?