kotlinx-lincheck icon indicating copy to clipboard operation
kotlinx-lincheck copied to clipboard

Support ThreadLocal variables

Open bbrockbernd opened this issue 8 months ago • 0 comments

The following test succeeds if we get the "threadLocal" from the concurrenthashmap (keyed by thread id), but fails if we get it from actually thread local.

class LincheckTest {
    val threadLocalCounters = ConcurrentHashMap<Long, AtomicInteger>()
    val counter = AtomicInteger(0)

    @Test
    fun modelCheckingTest(): Unit = ModelCheckingOptions()
        .iterations(0) // Change to 300 for exhaustive testing
        .addCustomScenario { 
            parallel { 
                thread { 
                    actor(::iinc) 
                    actor(::iinc)
                } 
                
                thread { 
                    actor(::gget)
                    actor(::gget)
                }
                
                thread {
                    actor(::gget)
                    actor(::gget)
                }
            }
        }
        .invocationsPerIteration(5_000)
        .hangingDetectionThreshold(100)
        .logLevel(LoggingLevel.INFO)
        .check(this::class.java)

    @Operation
    fun iinc(): Int {
        val add = getLocalCounter().getAndIncrement()
        return counter.addAndGet(add)
    }

    @Operation
    fun gget() = counter.get()
    
    // This one works
//    private fun getLocalCounter() = threadLocalCounters.computeIfAbsent(Thread.currentThread().id) { AtomicInteger(1) }
    
    // This one doesnt
    private fun getLocalCounter() = localCounter.get()
    
}

private val localCounter: ThreadLocal<AtomicInteger> = ThreadLocal.withInitial { AtomicInteger(1) }

bbrockbernd avatar Mar 13 '25 13:03 bbrockbernd