Skip to main content
added 192 characters in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues (this is one of the reasons functional programming is so popular).

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will need to lock, inspect, and update it atomically, so threads will block each other waiting for their turn. If you don't wrap your databasecounter check and update together in a critical section or transaction, you risk a TOCTOU situation. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT COUNT(*) FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also inherently fault tolerant and much simpler to QA.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will need to lock, inspect, and update it atomically, so threads will block each other waiting for their turn. If you don't wrap your database check and update together, you risk a TOCTOU situation. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT COUNT(*) FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also inherently fault tolerant and much simpler to QA.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues (this is one of the reasons functional programming is so popular).

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will need to lock, inspect, and update it atomically, so threads will block each other waiting for their turn. If you don't wrap your counter check and update together in a critical section or transaction, you risk a TOCTOU situation. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT COUNT(*) FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also inherently fault tolerant and much simpler to QA.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

added 5 characters in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will end up waiting forneed to lock, inspect, and update it atomically, so threads will block each other to finishwaiting for their turn. If you don't wrap your database check and update together, you risk a TOCTOU attacksituation. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT UserIDCOUNT(*) FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also much moreinherently fault tolerant and much simpler to QA.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will end up waiting for each other to finish. If you don't wrap your database check and update together, you risk a TOCTOU attack. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT UserID FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also much more fault tolerant.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will need to lock, inspect, and update it atomically, so threads will block each other waiting for their turn. If you don't wrap your database check and update together, you risk a TOCTOU situation. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT COUNT(*) FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also inherently fault tolerant and much simpler to QA.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

added 5 characters in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will end up waiting for each other to finish. If you don't wrap your database check and update together, you risk a TOCTOU attack. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT UserID FROM ( SELECT TOP 100 *UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also much more fault tolerant.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will end up waiting for each other to finish. If you don't wrap your database check and update together, you risk a TOCTOU attack. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT UserID FROM ( SELECT TOP 100 * FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also much more fault tolerant.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

Usually answer this by saying that I'll use synchronized block in Java or on Database side, I'll use Locking concept.

When we learn about multithreading, we are taught about locks, critical sections, transactions, etc. What we generally are not taught is that these are a last resort. Often you can solve concurrency problems without them, and when you can, you avoid a whole host of potential defects and performance issues.

If you are designing a fantasy sports application in which there's a contest which can handle only 100 users. If 99 users are already registered for the contest and multiple users hit the PARTICIPATE button at the same time to become the 100th user, then how will you handle this in your application?

The temptation here is to create a counter, check if it has reached 100, then increment it with every registration. This is not a great approach because it creates lock contention over the counter. All threads will end up waiting for each other to finish. If you don't wrap your database check and update together, you risk a TOCTOU attack. And if you acquire the locks in the wrong order, you risk a deadlock. Also, this solution has fault tolerance issues-- for example, if a process manages to increment the counter but throws an exception before it can register the user, it is nearly impossible to recover to a known good state.

Instead, this scenario can be handled very simply with this logic.

  1. When a user registers. store their user name with a datetime stamp specifying when exactly they registered, e.g

     INSERT Registration(UserID, RegistrationTime) VALUES (@UserID, GETDATE()) 
  2. To determine if their registration was accepted, select the top 100 users and see if the user is in it.

     SELECT UserID FROM ( SELECT TOP 100 UserID FROM Registration ORDER BY RegistrationTime ) WHERE UserID = @UserID 

This solution requires no locks or transactions other than the implicit transaction created by your insert statement, which is unavoidable. It's also much more fault tolerant.

If you are designing a chess game, where multiple users are selecting the users of same level of competence to play with them. Then suppose at same time, users A and B choose the user C (to play with) at the same time, then how will you handle this?

Again, some simple logic will avoid the need for excessive locking.

  1. Allow any number of players to join a game. Record the datetime of when they joined.
  2. Start the game when there are two or more players
  3. As the first step in the game, sort the players by the datetime that they joined, then boot the 3rd and later players.

You can certainly solve either of these problems with locks or transactions, but it is also easy to avoid those mechanisms and the challenges that accompany them.

added 1 character in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93
Loading
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93
Loading