当前位置: 动力学知识库 > 问答 > 编程问答 >

multithreading - Why does deadlock occur? Can't you release locks mid-process?

问题描述:

Suppose one person is trying to transfer $20 from bank account A to bank account B and another person is trying to transfer $30 from bank account B to bank account A at the same time. Why should this result in deadlock? Can't each thread do the following:

Thread 1

Acquire A's lock

Withdraw $20 from A

Release A's lock

Acquire B's lock

Add $20 to B

Release B's lock

Thread 2

Acquire B's lock

Withdraw $30 from B

Release B's lock

Acquire A's lock

Add $30 to A

Release A's lock

I understand that this would cause deadlock if the resources were released at the end of each thread. However, why can't a thread simply release a resource's lock as soon as it is done with the resource?

网友答案:

Suppose one person is trying to transfer $20 from bank account A to bank account B and another person is trying to transfer $30 from bank account B to bank account A at the same time. Why should this result in deadlock?

It wouldn't. That's not how real banking works.

You are presumably reasoning from some sort of analogy or simplified version that demonstrates the concept.

Thread 1 Acquire A's lock Withdraw $20 from A Release A's lock Acquire B's lock Add $20 to B Release B's lock

Something like this might well indeed be done in real code.

It's important to note that if for some reason we couldn't obtain the lock B we need to obtain the lock A again to return the $20, because if we can't return the $20 in the case of failure we don't have a transaction that will either succeed entirely or fail entirely, and that $20 can just disappear. Therefore if it's at all possible that after failing to obtain lock B we might fail to obtain lock A again, this would not be acceptable. It's also unacceptable if something might be obtaining locks on A and then B and making a decision based on the values they protect; the sum of them is incorrect at this point.

Another possible approach is to order locks. If A always comes before B then both threads will always attempt to get lock A before lock B no matter which way they are transferring money, and a deadlock will never occur. An important caveat is that if you have lock B and realise you also need lock A then you must release lock B before obtaining lock A.

Another possible approach is that on deadlock one transaction loses, its work undone and its locks released perhaps before a retry, or perhaps with an exception (or perhaps a certain number of retries before an exception). This is common in database locking.

网友答案:

Here is my opinion about this.

This is the steps of 1 thread to transfer money:

  1. Acquire lock A.
  2. Withdraw $20 from A.
  3. Acquire lock B.
  4. Add $20 to B.
  5. Release lock B.
  6. Release lock A.

So, why don't it release lock A after withdrawing $20 from A? Transferring money must be a transaction. It means that it's only marked as success after completing 6 steps above. If something's wrong, it has to roll back everything.

Let's imagine, at step 4, Add $20 to B, for some reason, it fails. That makes the thread roll back, add $20 back to A. At that time, if the lock A is occupied by other thread, it will lead to indefinite wait and some further problems.

That's why it has to hold the lock A until the transaction completed.

网友答案:

Deadlock Occurs when ,say 2 resource wait for each other to Free the resource. Consider you are passing through a narrow street through which, only a single person can pass at once, and suddenly you confront with another guy coming from opposite direction. Now you both will wait for each other to free up the resource ( Which is street ) and till then you both will be in deadlock state.

Here is 1st person has to transfer money from account A to B, he has to aquire both accounts to perform transaction from point A to B, Account holder 1 is waiting for account B to get freed, but , account holder 2 is waiting for account A to be freed , which , if you can imagine , form an infinite cyclic wait condition ( or deadlock ).

Now consider What you proposed above, Thread 1 can't free A's lock unless transaction is completed. What if this happens as you said ! what if After getting 20$ , thread A's lock is freed with deduction of 20$ and transaction to Account B failed due to any exception now transaction will have to be rolled back , suppose account A is being occupied by some other thread ! Can you see this may lead to indefinite wait and further exceptions of data inconsistency. Say User send 20$ to B , and deactivates his account immidiately after that, and if transaction fails, where will the money go?

The possible Solution to given scenario (After dead lock has been occured ) :

  1. No mutual Exclusion ( means no locking, nothing ! well you know better, what will happen if you leave your resource ( say Meat ) to hungry dogs (threads). your system will go to dogs eventually ( just kidding, simply : this is impossible to not follow principle of mutual exclusion )

  2. Allow preemption • OS can revoke resources from current owner

  3. No hold and wait • When waiting for a resource, must not currently hold any resource

  4. Request resources in order • When waiting for resource 'x', must not currently hold any resource 'y' • As you can see: If your program satisfies #3 then it satisfies #4

分享给朋友:
您可能感兴趣的文章:
随机阅读: