Introduction to Java Semaphores - Java Programming

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone in today's video we're going to talk  about semaphores within Java a semaphore is a way   that you can control the number of threads that  are going to access a certain shared resource   concurrently this is different from locks because  with a lock you have a thread that waits for a   lock gets it and then releases it when it's done  with a semaphore the concept of actually locking   a singular resource is decoupled from the number  of resources that you're trying to gain access to   so in the end it's another resource we programmers  can use when we need to deal with concurrency in   our code let's go ahead and pull up IntelliJ  and look at some examples so now that we have   IntelliJ up the first thing I'm going to do is  I'm going to create an instance of a software and what you'll notice is that we have to give  this Constructor an argument and the argument   that we're giving it is permits so what permits  means is this is the number of threads that can   access the resource or the condition that the  semaphore is going to protect so in this case   I'm going to make it a binary sum of four meaning  that only one thread can access the resources that   the semaphore is protecting and now that we've  made our semaphore let's go ahead and look at   some properties the common one you want to look  for is available permits this will tell you how   many more permits your semaphore has so if we run  this code and we have one which means that we can   have one more thread try to acquire the semaphore  and do something with the shared resource now what   I'm going to do next is I'm going to acquire  one of those permits so semaphore dot acquire   and this can throw in exception so we're going to  have to go ahead and let's go ahead and declare   the checked exception interrupted there and the  reason I can throw interrupted I'll get into   in a bit here but basically a choir can block if  there is a permit that's not available but for now   we're just going to grab the one immediately and  we're going to see that the number of available   decreases and now we hit zero as we expect and if  we want to reclaim the permit you can do release   and we'll see after we do a release that we're  back to one again so now go ahead and have my   semaphore take up to three permits I'll have it  call acquire twice and release once and we can see   that the level permits is two because we acquired  two and released one another thing to note here   is that acquiring and releasing is not necessarily  tied to multiple threads each time it's just often   semaphores are used in the context of concurrency  but they don't necessarily tie to individual   threat instances acquiring and releasing you  can actually have different threads release   permits that had been acquired by other threads  so you got to be careful whenever you are calling   the acquire and release methods that you know what  you're doing and with the thread that you're doing   it with likewise in the acquire method I can  acquire more than one permit so if I pass in   two right here then this will try to acquire two  out of the three permits that we have and then   you can see we acquired all three of ours between  these two acquire calls and then we released one   so what happens if we hit zero  and we try to acquire another one   so this acquire we would expect wouldn't be able  to acquire because all three of our permits have   already been acquired after this first line let's  go ahead and run the code and see what it does   tick tock tick tock tick tock tick tock okay our  program's hung and this is why we can have this   interrupted exception happen because if another  thread were to interrupt the current thread that   is trying to acquire the semaphore it would throw  an interrupted exception and that's why we have   to declare this here so basically we are waiting  for an acquire and now we're not doing anything so   we actually have to kill the program because it's  never going to acquire that permit so I mentioned   that semaphores are often used in the context of  multi-threading and concurrency so I'm going to   go ahead and rewrite the code to have multiple  threads involved and we're going to show some   other methods that we can use with semaphores  when we're dealing with multiple threads all right so walking through this code a little  bit and our main method we're creating an instance   of main because we're going to use a non-static  method here in a thread our semaphore here still   has three available permits then we have 100  threads actually we have let's go ahead and make   this 99 so now we have a hundred total threads  within our thread pool and we have 99 threads   that are each trying to acquire our semaphore  and then we have a sleep here and every second   we're checking to see how many threads are in  the queue trying to acquire our semaphore and   then within our try acquire method we attempt  and acquire so we block here until our place in   the queue is done and we can acquire the semaphore  we sleep for anywhere between zero to one seconds   and then we release the semaphore so let's run  the code and see what it does all right so we have   a Q length here and as you can see it's slowly  decreasing and that's because we had a whole bunch   of threads cued up at the front and now a lot of  threads are releasing the permit that they had on   the semaphore so then threads that were later in  the queue can now access it and I didn't handle   the case properly when we ended zero so but that's  fine this at least addresses the point of how you   can have multiple threads waiting to acquire  a semaphore and then you can have each of them   release though again the release of the semaphore  is different from locks you don't have to have   the same thread that acquired the semaphore also  release it you could have any thread do that and   one other thing I want to mention really quickly  is that the documentation does mention that the   Q length returns an estimate of the number of  threads the reason it's an estimate it mentions   here is because that value can change that  dynamically so essentially the get Q length that   doesn't block when it's reading the queue it gets  the current state of the queue and essentially   take a snapshot of it and then it looks it doesn't  update as each time that a new thread gets added   onto the queue so it gives us an idea it's not  always exactly accurate so I wouldn't rely on it   100 but it can give you kind of a general idea  of where things are at let's not moved on that   example the next thing I want to do is I want to  demonstrate something that might be a little more   applicable think about when you've got a server  and you need to essentially do some resource   throttling on the number of active connections  or user that your server is going to handle so   I've got this server that I've deployed and I'm  getting requests from clients let's say a million   requests and I want to limit it to a thousand  users how do I do that well one way you could do   it is you could have sent a fours essentially say  this is the number of users I'm going to handle   at one given time let's go ahead and start  implementing it and see how it could work   all right so let's create a new  class we're going to call it server   and what we're going to do first is  we're going to have a Constructor that   populates some information about our  server so we'll make a public server and it's going to have a number of users that it  can handle let's go ahead and make that a constant let's do 100 for now and then let's  go ahead and make our semaphore   we could go ahead and do that up  here as well private final semaphore and now since it's final we have  to Define it in the Constructor and our semaphore is going to be able to have a  total of num users available and then now I want   to have a login and a log out method so instead  of waiting because when you try to log in to a   server and it doesn't let you in should it really  spin or should I tell you hey I'm busy right now   I can't handle your request try again later  personally I don't like the spinning wheel of   death I like getting told immediately if there's  an issue and then to come back later and try again   so instead of blocking we're going  to do a try to acquire a semaphore   so to do that let's go ahead  and call our method try login and then we're going to return sum of four dot try acquire a try acquire  method basically doesn't block what it   does is that there's an available permit it  immediately acquires and if there's not an   available permit then it returns false and  doesn't acquire anything so the nice thing   about this is that it doesn't block your threads  indefinitely and you can get a return statement   to see if there's anything that's ready so  now we have a login now let's do a log out and for this all we have to do is send a four dot  release and now I also want some way to indicate   what the status of my server is so I'm going  to do that in a separate thread so I'm going   to make a private method which is essentially  just going to print the status of everything we'll just Loop indefinitely until we know  that we're done and we're gonna have to   handle interrupted exceptions let's go  ahead and sleep for a second initially   so I'll have to catch interrupted exception and let's wrap this in a runtime  exception so now in here what we   want to do is we want to indicate the number  of users that are currently on our server   so to do that you'd want to do num users minus sum  of four not available permits maybe think through   that basically we have number of users which is  100 and we want to look at the available permits   that are left meaning that if we start this would  be 100 this would be 100 meaning there are no   users on our server and then if all of our permits  are gone this will be zero so then we have 100   users on our system so now that we have our server  here let's go ahead and try to make some clients   that connect to this and update it we'll do that  in our main method here so we'll make a server and then we'll have another source of Random and then I'm going to create an Executor and I'm   going to go ahead and have it  submit a whole bunch of tasks all right so what we have here is we have  our executor service with 1000 requests so 1   000 threads and for each thread we are executing  the Lambda expression in here which is a runnable   and or doing is we are trying to log into  our server and while we can't log into the   server we sleep a random number of time between  0 and 999 milliseconds and then once we have the   semaphore acquired then we hold on to it for up to  a second and then we release it again so when we   are looking at how our server gets used let's go  ahead and now use the print status method so let's   just make a new thread and then have that execute  a runnable as well which will be this dot print   status and actually I'm going to make this a lot  simpler because this is just a method reference and I can delete those as well all right so now  what this should be doing is it should call Print   status and we're going to sleep for the first  second while our first few threads are acquiring   the semaphore and we are building up the number  of users on our system and then we're going to   iteratively keep servicing the number of users  that we want until we run out of users because   everybody finishes their login attempt let's go  ahead and run the code and see if it's doing that   whoops made a mistake I have to actually start  the thread that's what you get for not running   the code often enough will go ahead and try it  again all right that's better so now we have 100   users and now we're quickly decreasing and now  we have no more users okay let's go ahead and   stop the code and there are a few other things I  want to do to update this I want a better handle   when we have zero users left in our queue and I  want to see how many times we have users trying   to ask the server to log them in so I'm going  to modify the code to do those two things next all right so walking through the additions I  added in a login attempts field using a long   Adder a long Adder is essentially an efficient  version of an atomic long that was added in   Java 8 which when you're dealing with a lot of  different ads it is really efficient it uses a   little more space than an atomic long but  it's more efficient as far as performance   goes so that's why I decided to use it here  and what we're doing is we are incrementing   each time we call the trilogin method and then  within the print status method if our current   users equals zero we break out and we print out  that we have serviced all the requests otherwise   what we do is we print out the current  number of users and the login attempts   actually let me go ahead and also print out  the number of login attempts that this took all right so now that we have that there now  let's go ahead and run the code again and   see what it does all right there we go all right  interesting it took 4874 login attempts that time   now if we run it again it should be different  because we did randomize this a little bit and   that time it took 5126 and the current users were  already 36 there so it only took three additional   login attempts after that interesting and that  was an overview of semaphores within Java the   important thing to remember about a semaphore  is that the acquire and release methods don't   have any bearing on the thread that ran them  that is very different from Lock which is you   have a single thread that acquires an object  monitor as a lock then it releases the lock   when it's done that's a single thread doing all  that you could have one thread that handles the   entire semaphore acquire and release process  or you could have seven threads to it it's   completely arbitrary and up to the programmer  if you learned something new and you found this   video helpful please do give this video a thumbs  up I'd really appreciate it thank you all for   watching I hope you have a good rest of your  day and I hope to see you next time take care
Info
Channel: Will Tollefson
Views: 5,741
Rating: undefined out of 5
Keywords:
Id: g19pjkJyGEU
Channel Id: undefined
Length: 15min 23sec (923 seconds)
Published: Fri Sep 15 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.