0

I have multi threads that want to put a value in a TreeSet<Long>, in a part of code. The values are almost unique because they are System.nanoTime(). I clean the TreeSets periodically. Problem is that sometimes my threads got blocked in TreeSet.add() function. I used jconsole to watch thread states, threads are in RUNNABLE state and the stack trace shows this:

java.util.TreeMap.put(TeeMap.java:567)
java.util.TreeSet.add(TreeSet.java:255)
... //my program stack trace

I'm using jdk 1.7.0_60 for running program. Also I should mention in this situation cpu usage become 100%. My question is why the threads got blocked and how can I fix the situation? I looked at TreeMap code, but I didn't figure out problem, but I think problem relates to while loop in TreeMap.put().

vakarami
  • 576
  • 9
  • 22
  • 1
    And what; may I ask; have you used to synchronize access to the `TreeSet`? – Boris the Spider Nov 22 '16 at 10:25
  • @BoristheSpider no, it is not. is that the problem? – vakarami Nov 22 '16 at 10:27
  • 1
    Unless a `Collection` is explicitly designed as thread safe it cannot be accessed by multiple threads without a memory barrier. What you have created is a data race - congrats. – Boris the Spider Nov 22 '16 at 10:28
  • For multithreading, please use a ConcurrentHashSet – Arthur Eirich Nov 22 '16 at 10:28
  • @ArthurEirich no such thing... – Boris the Spider Nov 22 '16 at 10:29
  • At first I thought that what Boris the Spider wrote shouldn't be the matter. Then I understood that he may (and probably is) right - TreeSet probably uses some search tree. See: https://en.wikipedia.org/wiki/Search_tree ; https://en.wikipedia.org/wiki/AVL_tree ; https://en.wikipedia.org/wiki/Red%E2%80%93black_tree ; – Filip Malczak Nov 22 '16 at 10:30
  • @BoristheSpider Oops, my bad! Thought there was one since a ConcurrentHashMap exists. – Arthur Eirich Nov 22 '16 at 10:31
  • 1
    Also: would you look into javadocs of TreeSet ( https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html ) you could read: Note that this implementation is not synchronized. If multiple threads access a tree set concurrently, and at least one of the threads modifies the set, it must be synchronized externally. – Filip Malczak Nov 22 '16 at 10:32
  • Last, but not least: see https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedSet(java.util.Set) - it will be quite useful for you. – Filip Malczak Nov 22 '16 at 10:33
  • 1
    [This answer](http://stackoverflow.com/questions/6992608/why-there-is-no-concurrenthashset-against-concurrenthashmap#6992643) may help you – Arthur Eirich Nov 22 '16 at 10:33
  • thanks guys, my bad! I'v got it :) – vakarami Nov 22 '16 at 10:35
  • I understand that TreeSet is not threadsafe. But that would only create inconsistent state right? Why would it get stuck? – Kannan Ramamoorthy Feb 21 '23 at 17:06

1 Answers1

1

As it was mentioned in comments, the problem is that TreeSet is not thread safe and if we want to modify it (add or remove data) in multi threads, it must be synchronized externally.

vakarami
  • 576
  • 9
  • 22
  • Or, if performance is a concern (or, really even if it's not) you could use a [`ConcurrentSkipListSet`](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html) or [`Collections.newSetFromMap(new ConcurrentHashMap<>())`](https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#newSetFromMap(java.util.Map)). – Boris the Spider Nov 22 '16 at 14:17
  • Surprisingly using `Collections.newSetFromMap(new ConcurrentHashMap<>())` caused `ConcurrentModificationException`! At the end I used `ConcurrentSkipListSet` – vakarami Aug 21 '17 at 07:27
  • That exception does not mean what you think it means. – Boris the Spider Aug 21 '17 at 07:32