Lock组件

当我们用多进程来读写文件的时候,如果一个进程是写文件,一个进程是读文件,

如果两个文件同时进行,肯定是不行的,必须是文件写结束后,才可以进行读操作。

或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就需要锁机制进行控制。

需求:

一个进程写入一个文件,一个进程追加文件,一个进程读文件,同时启动起来

我们可以通过进程的join()方法来实现,这是一种方法,本节用Lock(进程锁)来实现。

函数说明:

# lock = multiprocessing.Lock()

# lock.acquire()                #获得锁

# lock.release()                #释放锁




先写不加锁的程序:

#不加锁

# number  +1

# number  +3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import  multiprocessing
import  time
def  add(number,value,lock):
     print  ( "init add{0} number = {1}" . format (value, number))
     for  in  xrange ( 1 6 ):
         number  + =  value
         time.sleep( 1 )
         print  ( "add{0} number = {1}" . format (value, number))
         
if  __name__  = =  "__main__" :
     lock  =  multiprocessing.Lock()
     number  =  0
     p1  =  multiprocessing.Process(target = add,args = (number,  1 , lock))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 , lock))
     p1.start()
     p2.start()
     print  ( "main end" )

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
main end
init add1 number = 0
init add3 number = 0
add1 number = 1
add3 number = 3
add1 number = 2
add3 number = 6
add1 number = 3
add3 number = 9
add1 number = 4
add3 number = 12
add1 number = 5
add3 number = 15


再写加锁的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import  multiprocessing
import  time
def  add(number,value,lock):
     with lock:
     print  ( "init add{0} number = {1}" . format (value, number))
     for  in  xrange ( 1 6 ):
         number  + =  value
         time.sleep( 1 )
         print  ( "add{0} number = {1}" . format (value, number))
         
if  __name__  = =  "__main__" :
     lock  =  multiprocessing.Lock()
     number  =  0
     p1  =  multiprocessing.Process(target = add,args = (number,  1 , lock))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 , lock))
     p1.start()
     p2.start()
     print  ( "main end" )

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
main end
init add1 number = 0             #add1优先抢到锁,优先执行
add1 number = 1
add1 number = 2
add1 number = 3
add1 number = 4
add1 number = 5
init add3 number = 0             #add3被阻塞,等待add1执行完成,释放锁后执行add3
add3 number = 3
add3 number = 6
add3 number = 9
add3 number = 12
add3 number = 15



使用 lock.acquire() 和 lock.release()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import  multiprocessing
import  time
def  add(number,value,lock):
     lock.acquire()
     try :
         print  ( "init add{0} number = {1}" . format (value, number))
         for  in  xrange ( 1 6 ):
             number  + =  value
             time.sleep( 1 )
             print  ( "add{0} number = {1}" . format (value, number))
     except  Exception as e:
         raise  e
     finally :
         lock.release()
 
if  __name__  = =  "__main__" :
     lock  =  multiprocessing.Lock()
     number  =  0
     p1  =  multiprocessing.Process(target = add,args = (number,  1 , lock))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 , lock))
     p1.start()
     p2.start()
     print  ( "main end" )

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
main end
init add1 number  =  0
add1 number  =  1
add1 number  =  2
add1 number  =  3
add1 number  =  4
add1 number  =  5
init add3 number  =  0
add3 number  =  3
add3 number  =  6
add3 number  =  9
add3 number  =  12
add3 number  =  15



共享内存

python的multiprocessing模块也给我们提供了共享内存的操作

一般的变量在进程之间是没法进行通讯的,multiprocessing 给我们提供了 Value 和 Array 模块,他们可以在不通的进程中共同使用


例子:不加锁,让number加完1后再继续加3,再继续加一,再继续加3...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import  multiprocessing
import  time
def  add(number,add_value):
     try :
         print  ( "init add{0} number = {1}" . format (add_value, number.value))
         for  in  xrange ( 1 6 ):
             number.value  + =  add_value
             print  ( "***************add{0} has added***********" . format (add_value))
             time.sleep( 1 )
             print  ( "add{0} number = {1}" . format (add_value, number.value))
     except  Exception as e:
         raise  e
         
if  __name__  = =  "__main__" :
     number  =  multiprocessing.Value( 'i' 0 )
     p1  =  multiprocessing.Process(target = add,args = (number,  1 ))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 ))
     p1.start()
     p2.start()
     print  ( "main end" )

打印结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
main end
init add1 number  =  0
* * * * * * * * * * * * * * * add1 has added * * * * * * * * * * *
init add3 number  =  1
* * * * * * * * * * * * * * * add3 has added * * * * * * * * * * *
add1 number  =  4
* * * * * * * * * * * * * * * add1 has added * * * * * * * * * * *
add3 number  =  5
* * * * * * * * * * * * * * * add3 has added * * * * * * * * * * *
add1 number  =  8
* * * * * * * * * * * * * * * add1 has added * * * * * * * * * * *
add3 number  =  9
* * * * * * * * * * * * * * * add3 has added * * * * * * * * * * *
add1 number  =  12
* * * * * * * * * * * * * * * add1 has added * * * * * * * * * * *
add3 number  =  13
* * * * * * * * * * * * * * * add3 has added * * * * * * * * * * *
add1 number  =  16
* * * * * * * * * * * * * * * add1 has added * * * * * * * * * * *
add3 number  =  17
* * * * * * * * * * * * * * * add3 has added * * * * * * * * * * *
add1 number  =  20
add3 number  =  20



再给加上锁:

加1的进程加完后,再执行加上3的进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import  multiprocessing
import  time
def  add(number,add_value,lock):
     lock.acquire()
     try :
         print  ( "init add{0} number = {1}" . format (add_value, number.value))
         for  in  xrange ( 1 6 ):
             number.value  + =  add_value
             print  ( "***************add{0} has added***********" . format (add_value))
             time.sleep( 1 )
             print  ( "add{0} number = {1}" . format (add_value, number.value))
     except  Exception as e:
         raise  e
     finally :
         lock.release()
         
if  __name__  = =  "__main__" :
     lock  =  multiprocessing.Lock()
     number  =  multiprocessing.Value( 'i' 0 )
     p1  =  multiprocessing.Process(target = add,args = (number,  1 , lock))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 , lock))
     p1.start()
     p2.start()
     print  ( "main end" )

执行结果(对比上面):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
main end
init add1 number = 0
***************add1 has added***********
add1 number = 1
***************add1 has added***********
add1 number = 2
***************add1 has added***********
add1 number = 3
***************add1 has added***********
add1 number = 4
***************add1 has added***********
add1 number = 5
init add3 number = 5
***************add3 has added***********
add3 number = 8
***************add3 has added***********
add3 number = 11
***************add3 has added***********
add3 number = 14
***************add3 has added***********
add3 number = 17
***************add3 has added***********
add3 number = 20


多进程共享内存实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import  multiprocessing
import  time
def  add(number,add_value,lock):
     lock.acquire()
     try :
         print  ( "init add{0} number = {1}" . format (add_value, number.value))
         for  in  xrange ( 1 6 ):
             number.value  + =  add_value
             print  ( "***************add{0} has added***********" . format (add_value))
             time.sleep( 1 )
             print  ( "add{0} number = {1}" . format (add_value, number.value))
         except  Exception as e:
             raise  e
         finally :
             lock.release()
 
def  change(arr):
     for  in  range ( len (arr)):
         arr[i]  =  - arr[i]
         
if  __name__  = =  "__main__" :
     lock  =  multiprocessing.Lock()
     number  =  multiprocessing.Value( 'i' 0 )
     arr  =  multiprocessing.Array( 'i' range ( 10 ))
     print  (arr[:])
     p1  =  multiprocessing.Process(target = add,args = (number,  1 , lock))
     p2  =  multiprocessing.Process(target = add,args = (number,  3 , lock))
     p3  =  multiprocessing.Process(target = change,args = (arr,))
     p1.start()
     p2.start()
     p3.start()
     p3.join()
     print  (arr[:])
     print  ( "main end" )

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
init add3 number = 0
***************add3 has added***********
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
main end
add3 number = 3
***************add3 has added***********
add3 number = 6
***************add3 has added***********
add3 number = 9
***************add3 has added***********
add3 number = 12
***************add3 has added***********
add3 number = 15
init add1 number = 15
***************add1 has added***********
add1 number = 16
***************add1 has added***********
add1 number = 17
***************add1 has added***********
add1 number = 18
***************add1 has added***********
add1 number = 19
***************add1 has added***********
add1 number = 20