# 同步執行緒

## 執行緒同步的問題

• 死鎖
• 競爭條件

### 1. 競爭條件

x = 0

def increment_global():

global x
x += 1

for _ in range(50000):
increment_global()

def main():
global x
x = 0

t1.start()
t2.start()

t1.join()
t2.join()

if __name__ == "__main__":
for i in range(5):
main()
print("x = {1} after Iteration {0}".format(i,x))

x = 100000 after Iteration 0
x = 54034 after Iteration 1
x = 80230 after Iteration 2
x = 93602 after Iteration 3
x = 93289 after Iteration 4

## 處理使用鎖定的競爭條件

acquire()方法

• 將值設定為True - 如果使用預設引數True呼叫acquire()方法，則執行緒執行將被阻止，直到解鎖鎖。

• 將值設定為False - 如果acquire()方法使用False呼叫，而False不是預設引數，那麼執行緒執行不會被阻塞，直到它被設定為true，即直到它被鎖定。

release()方法

• 如果鎖定被鎖定，那麼release()方法將解鎖它。 它的工作是如果多個執行緒被阻塞並且等待鎖被解鎖，則只允許一個執行緒繼續。

x = 0

def increment_global():

global x
x += 1

for _ in range(50000):
lock.acquire()
increment_global()
lock.release()

def main():
global x
x = 0

t1.start()
t2.start()

t1.join()
t2.join()

if __name__ == "__main__":
for i in range(5):
main()
print("x = {1} after Iteration {0}".format(i,x))

x = 100000 after Iteration 0
x = 100000 after Iteration 1
x = 100000 after Iteration 2
x = 100000 after Iteration 3
x = 100000 after Iteration 4

## 僵局 - 餐飲哲學家的問題

Edsger Dijkstra最初介紹了餐飲哲學家問題，這是著名的並行系統最大問題和死鎖問題之一。

Python程式的解決方案

import random
import time

running = True

def __init__(self, xname, Leftfork, Rightfork):
self.name = xname
self.Leftfork = Leftfork
self.Rightfork = Rightfork

def run(self):
while(self.running):
time.sleep( random.uniform(3,13))
print ('%s is hungry.' % self.name)
self.dine()

def dine(self):
fork1, fork2 = self.Leftfork, self.Rightfork

while self.running:
fork1.acquire(True)
locked = fork2.acquire(False)
if locked: break
fork1.release()
print ('%s swaps forks' % self.name)
fork1, fork2 = fork2, fork1
else:
return

self.dining()
fork2.release()
fork1.release()

def dining(self):
print ('%s starts eating '% self.name)
time.sleep(random.uniform(1,10))
print ('%s finishes eating and now thinking.' % self.name)

def Dining_Philosophers():
forks = [threading.Lock() for n in range(5)]
philosopherNames = ('1st','2nd','3rd','4th', '5th')

philosophers= [DiningPhilosopher(philosopherNames[i], forks[i%5], forks[(i+1)%5]) \
for i in range(5)]

random.seed()
DiningPhilosopher.running = True
for p in philosophers: p.start()
time.sleep(30)
DiningPhilosopher.running = False
print (" It is finishing.")

Dining_Philosophers()

4th is hungry.
4th starts eating
1st is hungry.
1st starts eating
2nd is hungry.
5th is hungry.
3rd is hungry.
1st finishes eating and now thinking.3rd swaps forks
2nd starts eating
4th finishes eating and now thinking.
3rd swaps forks5th starts eating
5th finishes eating and now thinking.
4th is hungry.
4th starts eating
2nd finishes eating and now thinking.
3rd swaps forks
1st is hungry.
1st starts eating
4th finishes eating and now thinking.
3rd starts eating
5th is hungry.
5th swaps forks
1st finishes eating and now thinking.
5th starts eating
2nd is hungry.
2nd swaps forks
4th is hungry.
5th finishes eating and now thinking.
3rd finishes eating and now thinking.
2nd starts eating 4th starts eating
It is finishing.