Exercise: Thread-Safe Voucher Redemption
Problem statement
In an e-commerce application, a user attempts to exploit a single-use $50 discount voucher by clicking “Apply” simultaneously from their smartphone and their laptop. If the backend does not synchronize the redemption check, both concurrent requests might read the voucher state as “unused” at the exact same millisecond, applying the discount twice. You must synchronize the redemption logic to ensure the voucher is only ever applied once.
Task requirements
Implement the
RedeemVouchermethod inside theVoucherServiceclass.Check if the voucher has already been used.
If it is unused, simulate a random processing delay, mark it as used, and return
true(success).If it is already used, return
false(failure).Ensure the check and the update happen as a single, indivisible operation.
Constraints
You must use the
lockstatement with a dedicated locker object to protect the critical section where the voucher state is checked and modified.You must use
Task.WhenAllin the test program to execute the concurrent requests simultaneously.
Good luck trying the exercise! If you’re unsure how to proceed, check the “Solution” tab above.
Get hints
Instantiate a
private readonly object _voucherLock = new object();at the class level to use as your lock token.Wrap the
if (!IsVoucherUsed)check AND the assignmentIsVoucherUsed = true;inside a singlelock (_voucherLock) { ... }block. Checking and modifying must be one atomic action.Notice that we use
Thread.Sleepinstead ofTask.Delay. This is because the C# compiler prohibits using theawaitkeyword inside alockblock!In the program file, pass both tasks into
Task.WhenAllandawaitit. It will return abool[]array containing the results of both requests.
Exercise: Thread-Safe Voucher Redemption
Problem statement
In an e-commerce application, a user attempts to exploit a single-use $50 discount voucher by clicking “Apply” simultaneously from their smartphone and their laptop. If the backend does not synchronize the redemption check, both concurrent requests might read the voucher state as “unused” at the exact same millisecond, applying the discount twice. You must synchronize the redemption logic to ensure the voucher is only ever applied once.
Task requirements
Implement the
RedeemVouchermethod inside theVoucherServiceclass.Check if the voucher has already been used.
If it is unused, simulate a random processing delay, mark it as used, and return
true(success).If it is already used, return
false(failure).Ensure the check and the update happen as a single, indivisible operation.
Constraints
You must use the
lockstatement with a dedicated locker object to protect the critical section where the voucher state is checked and modified.You must use
Task.WhenAllin the test program to execute the concurrent requests simultaneously.
Good luck trying the exercise! If you’re unsure how to proceed, check the “Solution” tab above.
Get hints
Instantiate a
private readonly object _voucherLock = new object();at the class level to use as your lock token.Wrap the
if (!IsVoucherUsed)check AND the assignmentIsVoucherUsed = true;inside a singlelock (_voucherLock) { ... }block. Checking and modifying must be one atomic action.Notice that we use
Thread.Sleepinstead ofTask.Delay. This is because the C# compiler prohibits using theawaitkeyword inside alockblock!In the program file, pass both tasks into
Task.WhenAllandawaitit. It will return abool[]array containing the results of both requests.