python錠とデッドロックの問題を話します。


オペレーティングシステムを学んだことがあれば、ロックについてはよく知らないはずです。ロックとは、スレッドロックを意味し、論理またはリソースを指定するために使用できます。同じ時間にスレッドのみアクセスできます。これはよく分かります。鍵をもらった人しか入れない部屋があるようです。部屋の入り口から鍵をもらって部屋に入ります。部屋を出る時は鍵をまた玄関に戻します。このようにして、次は入り口に行く人が鍵をもらうことができます。ここの部屋はある資源か論理か、鍵を持っている人はスレッドを指しています。
ロックの原因
ロックの原理が分かりました。なぜロックが必要なのですか?どのシーンで使われますか?
実際には、その使用シーンは非常に広く、私たちは非常に簡単な例を挙げると、タオバオ買い物です。私達はすべて知っています。店の在庫は全部限られています。一つは足りないです。今ある商品の在庫が一つしか残っていないと言えば、二人で同時に買うことになります。二人が同時に買うということは、二つの要求が同時に購買要求を提起しています。もしロックをかけないなら、二つのスレッドが同時に商品の在庫を調べます。0より大きいです。購買ロジックを行ったら、一つ減らします。二つのスレッドが同時に実行されるので、最後の商品の在庫は-1になります。
明らかに商品の在庫はマイナスであるべきではないので、このような状況を避ける必要があります。ロックをかけることでこの問題を完璧に解決できます。一度に一つのスレッドしか購入を開始できないと規定していますが、このように一つのスレッドが在庫を0に減らすと、二つ目の要求は修正できなくなり、データの正確性が保証されます。
コードの実装
Pythonの中で、私たちはどうやってこのロックを実現しますか?
実はとても簡単です。threadingライブラリの中でスレッドのツールを提供してくれました。直接持ってきて使えばいいです。私たちはthreadingの中のLockオブジェクトを使うことで、簡単にロックをかけることができます。

import threading

class PurchaseRequest:
  '''
         
  '''
  def __init__(self, initial_value = 0):
    self._value = initial_value
    self._lock = threading.Lock()

  def incr(self,delta=1):
    '''
       
    '''
    self._lock.acquire()
    self._value += delta
    self._lock.release()

  def decr(self,delta=1):
    '''
       
    '''
    self._lock.acquire()
    self._value -= delta
    self._lock.release()
コードの中からLockというオブジェクトの使い方が簡単に分かります。私たちはロックエリアに入る前に、まずロック・acquire()を使ってロックを取得します。ロックオブジェクトは、同じ時刻に1つのスレッドのみがロックを取得し、ロックを取得してから継続して実行することができます。私たちは実行が完了したら、ロックを「玄関に戻す」必要がありますので、再度release方法を呼び出して、ロックの解除を表します。
ここには小さい問題があります。多くのプログラマーはプログラムを作る時、いつもreleaseを忘れて、不必要なバグを引き起こします。また、この分散式シーンのバグはテストで発見するのが難しいです。テストの時は同時シーンをテストするのが難しいので、code reviewの時も見落としやすいです。漏れたら見つけにくいです。
この問題を解決するために、ロックはwith文を使うという改善的な使い方を提供しています。with文は前に文書を使う時使ったことがあります。withを使って私達の代わりにtry catchと資源回収などの仕事を完成できます。私達は使うだけで終わります。ここも同じです。withを使ったらロックの申請と釈放をしなくてもいいです。直接コードを書けばいいです。だから上のコードはこう書き換えられます。

import threading

class PurchaseRequest:
  '''
         
  '''
  def __init__(self, initial_value = 0):
    self._value = initial_value
    self._lock = threading.Lock()

  def incr(self,delta=1):
    '''
       
    '''
 with self._lock:
     self._value += delta

  def decr(self,delta=1):
    '''
       
    '''
    with self._lock:
     self._value -= delta
このように見えるのはさわやかで多いですか?
再入力ロック
上で紹介したのは一番簡単な錠です。私達がよく使うのは重入錠です。
ロックの重さは何ですか?簡単に説明しますと、スレッドがロックされている場合、再度ロックされたエリアに入ることができます。しかし、スレッドはまだロックを持っていますが、まだリリースされていません。それともロックエリアにいるべきではないですか?実はあるので、道理もとても簡単で、再帰します。
上の例を少し変えたら、全然違ってきます。

import threading

class PurchaseRequest:
  '''
         
  '''
  def __init__(self, initial_value = 0):
    self._value = initial_value
    self._lock = threading.Lock()

  def incr(self,delta=1):
    '''
       
    '''
 with self._lock:
     self._value += delta

  def decr(self,delta=1):
    '''
       
    '''
    with self._lock:
     self.incr(-delta)
上のdecr方法に注目して、私たちはincrで元のロジックに取って代わってdecrを実現しました。しかし、一つの問題はdecrもロックをかける方法であり、前のロックを解除してから入ることができます。しかし、もう鍵を持っています。この場合はロックが発生します。
私たちはロックをロックに換えるだけでこの問題を解決できます。コードを修正するだけでいいです。

import threading

class PurchaseRequest:
  '''
         
      RLock   Lock,           
  '''
  def __init__(self, initial_value = 0):
    self._value = initial_value
    self._lock = threading.RLock()

  def incr(self,delta=1):
    '''
       
    '''
 with self._lock:
     self._value += delta

  def decr(self,delta=1):
    '''
       
    '''
    with self._lock:
     self.incr(-delta)
締め括りをつける
今日はPythonにおけるロックの使い方と、ロックを再入力できる概念を紹介します。併発シーンでは下開発とデバッグは比較的難しい仕事で、ちょっと油断すると様々な穴を踏んでしまいます。
デッドロックの問題に対しては、Pythonは他の解決策も提供しています。次の文章の中に置いて、皆さんと共有します。
以上はpythonの同時ロックとデッドロックの問題の詳しい内容を話して、更にpythonの同時ロックとデッドロックの資料に関して私達のその他の関連している文章に注意して下さい!