Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Synchronizing instance variable  RSS feed

 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am having trouble making a servlet thread-safe using synchronization.

I do know it's best to avoid instance (state) variables in servlets, but my college assignment calls strictly for this.

My servlet has an instance variable, shared among any number of threads that run. I need to use synchronization such that modification of this variable is only allowed to one thread at a time. I then need to test the effects of synchronization employed by using a Thread.currentThread().sleep(10000) delay timer within the synchronized(){} block.

- The instance variable is of type double, so a number.
- I hence can't use it as monitor, as it's not an object.
- I hence set up synchronization blocks around code lines that modify this variable.
- The syntax I used for these synchronization blocks is as follows:

   

I researched a lot about servlets in this regard. My findings are the following:

- using the "this" word as synchronization object does not work, because "this" is its own "this" for each thread of the servlet running. So if 4 users have simultaneously the servlet open in their browsers and are using it, that means there are 4 instances of the servlet running and using "this", each instance simply refers back to itself -> meaning it is as if there is no synchronization condition anyway. For synchronization to work, all instances must lock on one single variable.
- Another finding states that there is always only one instance of a servlet running, and the multiple simultaneous users means multiple threads. But there is only one instance of the servlet.

This is conflicting information.

Please help: what should I do, how should I code, to synchronize operations using this instance variable, such that each next user (thread) must wait for the first thread to release the lock, before it can perform the operation???

There were suggestions as follows:

1) Construct a new object -> Object lock = new Object();
2) Use synchronization on the desired instance variable, using the object as a "dummy" reference -> synchronize(lock){// Code with variable}.

This still did not work. Currently the servlet behaves as if there are no synchronized blocks at all. Help is hugely appreciated!
 
ramya srei
Greenhorn
Posts: 3
Java Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you could use synchronized get/set methods or processing methods to access the instance variables

please read
http://docs.oracle.com/javaee/5/tutorial/doc/bnafo.html#bnafs
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why don't you try it out? Write a servlet that blocks for a few seconds and send multiple requests. Then see if the requests have to wait on each other.
 
Norm Radder
Ranch Foreman
Posts: 2240
28
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, guys, I will go through the suggested documents/forum pages and try the suggestions, then get back to you on whether I succeeded.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guys, I tried the suggested - instead of synchronizing blocks of code (and having the issue of how to specify the object or item to lock on), I now synchronized the entire methods that perform the various operations with the balance. The issue persists, though. When I test with the sleep delay timer, any other operation invoked within less than 10 seconds after adding an amount to balance, still shows already the updated amount, meaning the synchronization does not work.
 
Norm Radder
Ranch Foreman
Posts: 2240
28
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please post the code you are testing so we can see what you have done.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And also show us what values you are expecting to appear and where.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, guys. The following is the entire code of my servlet - there are also comments for most actions so I think the code explains itself well.



You will see in the method that adds the entered amount to the balance, there is the delay timer (sleep) coded so as to keep the method lasting for 10 seconds and be able to test what happens when 2 threads try to refer to the balance variable simultaneously.

To answer the question of what I expect the servlet to do upon execution of 2 (or more) threads:

- Surely if the method that adds to balance, running the sleep delay, causes the itself to execute for at least 10 seconds, this means that if another thread executes any operation with this shared instance variable "balance" before those 10 seconds elapse, this other thread should not see the updated balance variable yet. To put it into a testing example:

1) I open 2 threads of the servlet in the browser.
2) In one of them I type 5000 in the amount text box and click "Deposit". This should trigger the addition method and in this case as coded, the delay timer inside that method.
3) If I rapidly switch over to the other thread and click "Balance" (which brings up to screen the current balance), before the 10 seconds elapsed in the first thread running and completing the addition method - then the balance shown by this second thread must be what it was before the first thread had the addition method triggered, that is, the first thread's method should not yet have finished, and thus "balance" was unchanged.

What happens, though, is, if I do the above as a test, as soon as I switch over to the other thread and click "Balance", it brings up the NEW balance, meaning the first thread instantly added and overwrote the variable, without delaying by 10 seconds.

I did test the delay code syntax in another program - it works as should. Hence I think there is an issue with how I use synchronization.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why would two threads be referring to the balance at the same time?
This has clearly been coded for a single user, as there's a single balance...
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So in the above example. the second thread should show $0 if you click "Balance" before 10 seconds elapse. However, it already shows $5000 - as was added in thread #1. But there is no delay.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your sleep is coded to occur after you've added 5000 to the balance.
So that is the balance that is used when the other thread uses it.

The synchronise here has no effect whatsoever as the only one thread is using the synched code.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Dave.

What you just said is also my suspicion, since I learned about instances and threads. Maybe you could correct me, but evidently I'm misunderstanding servlet instances and threads:

I have read from many sources and understood it as: there is one servlet .class file. But multiple users on multiple computers can hit the URL to open the servlet and use the servlet. Then it is said that each user is utilizing an instance of the servlet.

At the same time I read regarding similar problems that each thread uses its own copy of the servlet class and instance variable. According to this, then it makes sense that if each thread creates its own copy of the "balance" variable, which it then proceeds to use -> there is then never a condition where one copy of "balance" is accessed by more than one thread.

Now, the above information is conflicting. Could you please help to clarify where I misunderstand?

You noted that the way the servlet is written is for a single user, yet this is how the textbook instructs to code the servlet: to use an instance variable for the balance. Then you must test for yourself what happens when multiple threads use this servlet simultaneously and change the variable, and the change reflects on all threads' "balance".

How am I to code this then, using an instance variable, for multiple users?
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave, as to why 2 threads would refer to the same balance simultaneously - since my understanding as stated above that multpile threads (instances of servlet) share this common variable "balance", it means that in the possible scenario of more than 1 user using the servlet at the same time, those multiple uses might also be such that more than 1 user attempts to use same servlet function (coded method) at same time, hence requiring simultaneous access to the "balance" variable.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave.

Regarding the location of the sleep() code-line within the addToBalance() synchronized method:

I did consider your point before, and after I posted the code you saw, I actually swapped the order of code to add to and overwrite balance and perform the delay. It made no difference.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As I said in the earlier thread, there is one instance of the servlet.
That's it.

It's why the have to be threadsafe, and shouldn't have any state.

In your current set up, because there is only one instance of SyncBank, then there is only one balance value for every request, no matter who it comes from.
That is why web applications that need to track a session either store such things in the session itself, or store it in a database usually based on some user name, which would involve some form of logging in.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yevgeni Duvenage wrote:
I did consider your point before, and after I posted the code you saw, I actually swapped the order of code to add to and overwrite balance and perform the delay. It made no difference.


So, where is the sleep now?
What does the code look like?

Ah, hang on, didn't notice that formatBalance was synchronised.
So what's happening is the first request sleeps inside the synch'd addToBalance() method, then the second request comes in and ends up calling formatBalance, but because the first thread already has a synch lock on the servlet formatBalance cannot do anything until addToBalance actually finishes.

At least, that's what it looks like to me.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Dave.

The sleep() is now still inside the addToBalance() method, but is coded before the lines that add entered amount to the balance variable, so:

...addToBalance()
{
     Thread.currentThread().sleep()...                // First delay the addition procedure by 10 seconds.
     balance = balance + amount...                   // Then add to the balance.
}

It does make sense what you say about rather using session attributes for multi-user servlets, and thing is my next task (modification to this servlet) will be just that. But as per instruction of this task under discussion here, I am not to use session procedures yet. So I am trying to figure out why the synchronization doesn't work as intended.

I need to ask - when one thread waits on another to finish a certain process, how would this look in the browser? Would it be a blank screen in the waiting thread, with a "please wait" mouse cursor, or should everything refresh/load as usual, except that values being locked will not be updated by the other thread that tries to interfere, until the first thread finishes with its synchronized process?
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The next task I am to do indeed instructs to remove instance variables and use session attributes, with which no synchronization is needed and multiple threads will not interfere with one another.

But the current task in discussion instructs me to synchronize access to this instance variable. Is there then really no way to achieve this?
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As it stands, the browser of the second request will be waiting for the response to come back, which won't happen until the other thread has released its lock and handed over to the paused thread.

As for what you want to happen, I'm not sure I understand what you are trying to achieve.

You are (sort of) synch'ing access to the variable, in that all bits of code that access or modify it are synch'd.

If you want the incoming display request to still work while the other request is still "processing", ie locked, then remove the synch from the formatBalance code.  That may cause issues with the "shared" formattedBalance variable, though.
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to add some logging statements. In your synchronized statements, log when you're entering the method and when you're exiting the method, and also log the current instance of the servlet. It should print the servlet's hash code, which will give you a hint whether the different requests use the same servlet instance (they should).

Since you're silently catching interruptions, you also don't know if that could be an issue.
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:As it stands, the browser of the second request will be waiting for the response to come back, which won't happen until the other thread has released its lock and handed over to the paused thread.

This is what Yevgeni wants to happen. It's not happening.

As for what you want to happen, I'm not sure I understand what you are trying to achieve.

The exercise is to see that using synchronization to make servlets thread-safe is a bad idea, because it introduces a lot of latency. The next exercise will show that making servlets stateless is much better.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:
Dave Tolls wrote:As it stands, the browser of the second request will be waiting for the response to come back, which won't happen until the other thread has released its lock and handed over to the paused thread.

This is what Yevgeni wants to happen. It's not happening.


It is happening.
That's why the value from the second request is coming back as 5000.
The lock on the servlet is only released when the addBalance method finishes, and at that point the formatBalance can run for the other thread.

What's happening is:

First thread -> addBalance grabs lock and sleeps
Second thread -> calls formatBalance, but has to wait for the above
First thread -> addBalance wakes up and finishes (balance is now 5000), releasing the lock
Second thread -> (likely) grabs the lock and formats the balance (which is 5000) and releases the lock, sends response
First thread -> Calls formatBalance and waits (possibly) on the above, and releases, then sends response.



Stephan van Hulst wrote:
As for what you want to happen, I'm not sure I understand what you are trying to achieve.

The exercise is to see that using synchronization to make servlets thread-safe is a bad idea, because it introduces a lot of latency. The next exercise will show that making servlets stateless is much better.


Possibly, but there's just something wrong in the example in that every request shares a single balance.
That's the bit that is a disconnect for me.
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because if there wasn't a shared balance, there would be no point in synchronizing the methods.

Yevgeni, can you please describe concisely what the exact problem is you're having right now, and post the most up to date version of the relevant code that you're having problems with?
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:Because if there wasn't a shared balance, there would be no point in synchronizing the methods.

Never mind, I could have sworn the session was thread-safe. Instead of a balance variable, the session can be used.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan, Dave, the following is the current code I have:



I will try to clarify what I expect as the result:

1) 2 threads (browser windows) of servlet are open. Servlet is in initial state with variable "balance" at zero.
2) In one thread I type an amount and click "Deposit", which, by the code you see, should first sleep for 10 seconds, then perform the actual addition and overwriting of the balance.
3) Switching rapidly to the other thread (before the 10 seconds elapse), I click "Balance" and trigger the method that gets current balance number, formats it and renders to screen.
     - because the addToBalance() method is synchronized and also should run for at least 10 seconds, I expect the second thread to NOT show the updated balance unless 10 seconds have passed. Because as we are discussing,
        the thread must wait for the first thread to release the lock on the "balance" variable.
     - however, the second thread does not wait at all and displays the new balance instantly -> as if no synchronization and/or sleep() were ever used in the code.

Like was said in this post, the instance variable "balance" is shared among threads, so synchronizing on it should cause other threads to wait while the first finishes using it, but as you can see, this does not happen.
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, neither your showBalance() method nor any of the methods it calls lock on your servlet, so it doesn't block until it receives the object lock.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As Stephan suggested earlier, add some logging int here so you can see what's happening, because that code should be showing the balance as zero, since the sleep is prior to the modification., but as he says, in the above code there is no synching during the showBalance code.

Note, you are not locking on balance, you are locking on the servlet instance.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, guys.

Firstly, Stephan says I am not locking on the servlet, while Dave says I am locking on the servlet. Contradiction here, so am I or am I not?

Also, you are saying that by synchronizing a whole method I lock on the servlet instance - what exactly do you mean?

You also say that because the showBalance() method is not synchronized, that is why I am having the problem we're discussing, but isn't synchronization only needed when trying to modify and overwrite a variable? I mean the showBalance() method only reads the balance variable, then formats it for display. It does not change its value. So then it's only the addToBalance() and subtractFromBalance() methods (which actually change the balance variable) that need to be synchronized.

But again, I tried synchronizing methods and this is not working, and I also tried synchronizing blocks of code containing operations with variable "balance" - so say instead of synchronizing the whole addToBalance() method, I would synchronize only inside it the part that refers to and overwrites "balance". But in the case of synchronizing just a block of code, how exactly do I lock onto it?

"balance" is not an object, but a double, so I can't use . How would I do this? And why should synchronizing on block of code instead of whole method make any difference?

Sorry, but being rather new to Java, I'm still trying to understand things that veterans here of course know backwards.

Thanks.
 
Dave Tolls
Rancher
Posts: 2914
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan has said the call to showBalance() doesn't result in a lock on anything...because there is nothing in that flow that is synchronised.
I'm saying that the lock you do use (in the add flow) is on the servlet.  That's what happens when you synchronise a method...you get a lock on the associated object.

As for what you should be doing I can't say, because this whole exercise makes no sense to me at all.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, Dave.

Then I really need to confirm something:

Say, you have methods A, B and C which do different things but all refer to and modify "balance" variable.
Say, only method A is synchronized, meaning that while it executes operating on "balance", the other 2 have to wait. That is if all works as must.
Do these other 2 methods need to be synchronized for the above to happen?

I thought that as long as one method keeps a lock on the variable (is synchronized), that already means that any other methods, synchronized or not, will HAVE to wait for access to the variable. Or is this wrong understanding and you have to "mark" each method as synchronized so that Java knows that all these (marked synchronized) methods are the ones that may possible try interfering with one another and therefore these are the ones that will wait on one another?

So in this context, my thinking was that even though showBalance() is not synchronized but addToBalance() is, if addToBalance() executes, and thus has the lock on "balance", it implies that showBalance() will have to wait for access to "balance". I am unclear on this...

Then about what you said of me locking on the servlet instead of the variable, when I synchronize a method - how to lock on the variable then? Use block of code? But then what do I do to make the variable an object or how do I lock onto it?

What is more absurd then about this exercise, is that the book tells me to "...use synchronized blocks of code or METHODS". It's hard to believe the possibility of there being so many errors in a textbook all in one task instruction?

This really is confusing...
 
Stephan van Hulst
Saloon Keeper
Posts: 7808
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't lock on a variable. You lock on an object. For synchronized methods, the object that the method being called on is the object being locked on. For static methods, the class object is the object being locked on. For synchronized blocks, you explicitly pass the object to lock on. Two threads can not simultaneously run pieces of code that lock on the same object. If a thread doesn't try to lock on an object, it doesn't block.

Here's an informative article: https://www.javaworld.com/article/2076797/java-concurrency/programming-java-threads-in-the-real-world--part-2.amp.html
 
Paul Clapham
Sheriff
Posts: 22502
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yevgeni Duvenage wrote:Firstly, Stephan says I am not locking on the servlet, while Dave says I am locking on the servlet. Contradiction here, so am I or am I not?


Both are right. One of them confirmed that your synchronized methods are locking on the servlet; the other pointed out that your methods which aren't synchronized aren't locking on anything.
 
Yevgeni Duvenage
Greenhorn
Posts: 28
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I read the article. It points out that (for some reason) if one method that is synchronized, is being locked for use by some thread, then all other methods that are coded as synchronized are locked as well. That does not make sense to me, why would the program only be able to run one method at a time instead of being able to run any of its methods, depending on what simultaneous threads require?

I understand that "balance", as it is, cannot be locked on as it is not an object. I understand also that synchronized methods lock onto the class.

The article also shows examples of code in which an Object is created within the class and is used as monitor, or, things like int data are defined not as simple int but as int arrays, so that you could create and object of them and then lock onto that object for synchronization.

Should I then attempt likewise with my double "balance" variable? Declare it instead as an array and set it as object, then lock directly onto it in synchronization blocks?
 
Paul Clapham
Sheriff
Posts: 22502
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yevgeni Duvenage wrote:I read the article. It points out that (for some reason) if one method that is synchronized, is being locked for use by some thread, then all other methods that are coded as synchronized are locked as well. That does not make sense to me, why would the program only be able to run one method at a time instead of being able to run any of its methods, depending on what simultaneous threads require?


You should stop working on this exercise until you understand the answer to that question. It's the central point of synchronization and you seem to be missing several important things.

The first thing you seem to have missed is that synchronization controls access to code from more than one thread. So "Why would the program only be able to run one method at a time..." misses the point -- it's whether code in two different threads can access certain pieces of code at the same time. There's more, but you already have a tutorial at hand so I'm not going to try writing my own tutorial here. I'd suggest you take some time to go through the tutorial and work through its code examples.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!