LoranceChen LoranceChen - 6 months ago 35
Java Question

Thread stuck when use java ConcurrentSkipListSet add method

I'm using ConcurrentSkipListSet collection to deal with concurrent operator. I find it will stuck sometimes, reproduct with this code:

import java.util.Comparator
import java.util.concurrent._

object SetDeadLock extends App {
private val tasks = new ConcurrentSkipListSet[Task](new Comparator[Task](){
override def compare(o1: Task, o2: Task): Int = {
val compare = (o1.systemTime - o2.systemTime).toInt
if (compare == 0) 1 else compare //distinct same time task
}
})

for(i <- 1 to 20) {
tasks.add(Task())
println(s"added - $i")
}

case class Task() {
val systemTime = System.currentTimeMillis()
}
}


Output

added - 1
added - 2


It perhaps stuck at others, besides, the comparator custom sort data method especially they are same (because Set not support same element) and all
Task
is new instance, it shouldn't be conflict with others.

with
jstack
cmd, the main thread stuck

at java.util.concurrent.ConcurrentSkipListMap.findPredecessor(ConcurrentSkipListMap.java:685)


does it was a bug or I just misleading some principle?

Thanks any help or advise.

UPDATE

I just now try modify
if (compare == 0) 1 else compare
to
if (compare == 0) -1 else compare
, surprising, I works well!

Does anyone could clarify how it work? Source code its difficult for me(and I think many people agree with me), after all, jdk do many works for machine execute speed not for code reader.

Finally

To avoid the awkward situation just make some different factor to
comparator
which match
Set
's semantics, such as appends a random value.But I think its will be better find another real suitable collection.

With a few days ago, I find a good idea to use hashCode as second verify when systemTime equals. hope helpful~

Answer

Your comparator is not stable. I don't think ConcurrentSkipListMap promises to behave nicely when different calls give inconsistent results. For instance, depending on how you call, you can think both a < b and b < a at the same time with your code.