MyBatis version

3.5.4

Database vendor and version

Test case or example project

MapperProxy#cachedInvoker {methodCache.computeIfAbsent} In ConcurrentHashMap#computeIfAbsent, the following code will cause lock acquire: [ else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); else { boolean added = false; // Here, even if the method and corresponding MapperMethodInvoker already exist synchronized (f) { ] I think, for mybatis, this lock is not necessary, maybe should change the code like follow: [ MapperMethodInvoker invoker = methodCache.get(method); if (invoker == null) { MapperMethodInvoker newInvoker = ....... MapperMethodInvoker old = methodCache.putIfAbsent(newInvoker); if (old != null) { invoker = old; } } return invoker; ]

Steps to reproduce

Expected result

Actual result

Comment From: harawata

That is a JDK's issue rather than MyBatis'. And it actually is fixed in JDK 9 and the backport to JDK 8 is also planned, it seems.

As MyBatis still supports Java 8, I thought about adding a preliminary check as you proposed, but it didn't make much difference (here is the JMH project that I used). Do you have any benchmark data proving otherwise?

[EDIT] Well, the benchmark should be done using multiple threads, obviously. I will re-test later.

Comment From: harawata

@lixinwen ,

I updated the JMH project and verified the effect of the preliminary check under heavy load. Does #1934 look OK to you?

Comment From: lixinwen

@harawata Thank you, this what i want.

Comment From: harawata

You can verify the fix with 3.5.5-SNAPSHOT. Thank you for taking the time to report, @lixinwen !