Skip to content

Conversation

omercelikceng
Copy link
Contributor

Replace synchronized methods and blocks with ReentrantLocks in a few classes in Spring Functions Catalog to improve compatibility with virtual threads. This changes the synchronization mechanism in:

CassandraConsumerConfiguration.PayloadToMatrixTransformer
InMemoryTraceRepository

The change helps avoid blocking virtual threads when using Spring Functions Catalog in Project Loom environments while maintaining thread safety.

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s see if such an action is really necessary is those cases: https://mikemybytes.com/2024/02/28/curiosities-of-java-virtual-threads-pinning-with-synchronized/!
In other words: if there is really no blocking operation inside that synchronized, no reason to change it. Plus it looks like some changes are coming to Java down the road : https://openjdk.org/jeps/491

@omercelikceng
Copy link
Contributor Author

omercelikceng commented Nov 28, 2024

Let’s see if such an action is really necessary is those cases: https://mikemybytes.com/2024/02/28/curiosities-of-java-virtual-threads-pinning-with-synchronized/! In other words: if there is really no blocking operation inside that synchronized, no reason to change it. Plus it looks like some changes are coming to Java down the road : https://openjdk.org/jeps/491

@artembilan Thank you very much for all the valuable information you provided. The links you provided contain really great information. I will read the links you sent again and again; they are really great.

However, I believe that ReentrantLock offers us more flexibility. Additionally, ReentrantLock provides features like interruptible lock acquisition, timed lock attempts, and finer control with the Condition API, which are not available with synchronized. Of course, the current code doesn't involve very complex operations, but I don't think ReentrantLock would introduce significant overhead either. Therefore, I think we could implement this improvement instead of using synchronized. However, if you disagree, I can close the pull request.

@artembilan
Copy link
Member

Sure! I’ll give it a second look when back from vacation next week .

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add your name to the @author list of the affected classes.

/**
* Flag to say that the repository lists traces in reverse order.
* @param reverse flag value (default true)
*/
public void setReverse(boolean reverse) {
synchronized (this.traces) {
try {
this.tracesLock.lock();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need any locking in setters at all.

Copy link
Contributor Author

@omercelikceng omercelikceng Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@artembilan I think locking is necessary here because the add method on line 86 uses the reverse and capacity values. In the add method, additions and removals are performed on the traces list using the reverse and capacity values.
add method requires locking, as any changes to reverse or capacity while the add method is being called could result in an inconsistent state. So, we need to lock both the add method and any other parts of the code that can modify the traces and reverse variables used by the add method. Therefore, I believe we should continue using locking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you are explaining is correct, but that's not realistic.
This class is created only once on Application context initialization.
Those setters are called at this point and only once.
Calling them at runtime is really mocking of the lifecycle of the instance of this class.

We should just agree that we are in Spring, so there are some undocumented rules for singleton beans where we just initialize them once. Plus the instance of this class is created by the configuration in this module.
You just need to drop the jar into your classpath - and everything will be auto-configured for you.

Why do we need the extra logic which may not have power in 99% of usage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I understand what you mean. Thank you. In that case, I will remove both the lock and the synchronized.

}

public List<Trace> findAll() {
synchronized (this.traces) {
try {
this.tracesLock.lock();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like this operation needs any locking at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@artembilan I think the same way here as well; we shouldn’t remove the locking from this part either.

@artembilan artembilan added this to the 5.1.0 milestone Dec 2, 2024
@artembilan artembilan added the type: enhancement A general enhancement label Dec 2, 2024
/**
* Flag to say that the repository lists traces in reverse order.
* @param reverse flag value (default true)
*/
public void setReverse(boolean reverse) {
synchronized (this.traces) {
this.tracesLock.lock();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You just removed our conversion on the matter, but still left lock in the setter.
🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once our conversation is finished, I was going to remove them. I'll take care of it right away.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that conversation has not been finished.
You just didn't wait for my response.
I am the owner of the project, that the final decision is on me.

Please, don't remove any conversation: it will be helpful in the future when some one would try to figure out what was an origin of this or that code.
Like exactly someone would ask why the synchronized as removed here and lock not added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just thought I would make another commit after our conversation. Of course, I’ll follow your guidelines. I didn’t mean to do anything wrong, sorry if I caused any confusion.

@omercelikceng
Copy link
Contributor Author

@artembilan I've applied the changes you recommended. And thank you for your guidance.

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good, but I cannot merge it yet until I cut 5.0.x branch.
We are planning to release 5.1.0 soon enough.
Thank you!

@omercelikceng
Copy link
Contributor Author

All good, but I cannot merge it yet until I cut 5.0.x branch. We are planning to release 5.1.0 soon enough. Thank you!

Thank you very much for everything. Best regards.

@artembilan artembilan modified the milestones: 5.1.0, 5.0.2 Dec 6, 2024
@artembilan artembilan merged commit 29541a5 into spring-cloud:main Dec 6, 2024
3 checks passed
@artembilan
Copy link
Member

@omercelikceng ,
I've changed my mind.
Since it looks like we are going to have 5.0.2 soon enough, this is a good candidate to be included there having its only internal nature.
Thank you and looking forward for more!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants