(python) mutex

The data between processes is not shared, but the same resources can be shared, so there is no problem in accessing the same file or the same printing terminal, but sharing brings competition, and the result of competition will be confused.

See below for printing three people's information concurrently:

from  multiprocessing import Process
import random,time

def task1():
    time.sleep (random.randint (1,3))
    print('task1: name, xxx')
    time.sleep (random.randint (1, 3))
    print('task1: age, 34')
    time.sleep (random.randint (1, 3))
    print('task1: gender: male')

def task2():
    time.sleep (random.randint (1,3))
    print('task2: name, thirteen is')
    time.sleep (random.randint (1, 3))
    print('task2: age, 34')
    time.sleep (random.randint (1, 3))
    print('task2: gender: male')

def task3():
    time.sleep (random.randint (0, 2))
    print('task3: name, 5 kings')
    time.sleep (random.randint (0, 2))
    print('task3: age, 34')
    time.sleep (random.randint (0, 2))
    print('task3: gender: male')

if __name__ == '__main__':

    p1=Process(target=task1)
    p2=Process(target=task2)
    p3=Process(target=task3)

    p1.start()
    p2.start()
    p3.start()
  
The results are as follows:


It can be seen from the results that the efficiency of concurrent operation is high, but the concurrent competition for resources brings confusion in the printing information.

So how to control, is to lock processing. Mutex means mutual exclusion. We can compare multiple processes to multiple people. The working principle of mutex is that multiple people compete for a common resource: for example, if multiple people want to go to the same bathroom, one person grabs the Put a lock on the back of the bathroom, and everyone else is waiting outside. After this person finishes unlocking, others can fight for it again. Therefore, the original title of the mutex is to change a certain function concurrently to serial. Although the efficiency is reduced, it ensures that the data security is not chaotic.

rom  multiprocessing import Process,Lock
import random,time

def task1(lock):
    lock.acquire()#Get the lock
    time.sleep (random.randint (1,3))
    print('task1: name, xxx')
    time.sleep (random.randint (1, 3))
    print('task1: age, 34')
    time.sleep (random.randint (1, 3))
    print('task1: gender: male')
    lock.release()#release the lock

def task2(lock):
    lock.acquire()
    time.sleep (random.randint (1,3))
    print('task2: name, thirteen is')
    time.sleep (random.randint (1, 3))
    print('task2: age, 34')
    time.sleep (random.randint (1, 3))
    print('task2: gender: male')
    lock.release()

def task3(lock):
    lock.acquire()
    time.sleep (random.randint (0, 2))
    print('task3: name, 5 kings')
    time.sleep (random.randint (0, 2))
    print('task3: age, 34')
    time.sleep (random.randint (0, 2))
    print('task3: gender: male')
    lock.release()

if __name__ == '__main__':
    mutex=Lock()

    p1=Process(target=task1,args=(mutex,))
    p2=Process(target=task2,args=(mutex,))
    p3=Process(target=task3,args=(mutex,))

    p1.start()
    p2.start()
    p3.start()

The results are as follows:


That way it won't be messed up.

Emphasis: it must be lock.acquire() once, and then lock.release() to release it once, in order to continue lock.acquire(), not continuous lock.acquire()

The difference between mutex and join():

Major premise: The principle of both is the same, both turn concurrency into serial, so as to ensure order

Difference 1: join is executed in an artificially specified order, while mutex locks are all processes competing equally, and whoever grabs the first will execute first.

Difference 2: Mutex locks can serialize part of code (code that modifies shared data), while join can only serialize code as a whole.

Let's take a look at a small example of grabbing tickets:

# The content in the db.json file is {"count": 100}
from multiprocessing import Process,Lock
import json ,time
import random

def search(name):
    dic=json.load(open('db.json','r',encoding='utf-8'))
    time.sleep(random.randint(0,2))#Simulate network delay
    print('%s found that the remaining votes are %s '%(name,dic['count']))

def get(name):
    dic = json.load(open('db.json', 'r', encoding='utf-8'))
    time.sleep(0.3)#simulate network delay
    if dic['count']>0:
        time.sleep(0.1)#simulate network delay
        print('%s successfully bought the remaining %s ticket'%(name,dic['count']))
        dic['count'] -= 1
        json.dump(dic,open('db.json','w',encoding='utf-8'))

def rob_ticket(name ,lock):
    search(name)
    with lock: # Equivalent to obtaining lock.acquire(), after executing the code body, automatically execute lock.release()
        get(name)

if __name__ == '__main__':
    lock=Lock()
    for i in range(100):
        name='Passerby %s'%i
        p=Process(target=rob_ticket,args=(name,lock))
        p.start()

Summarize:



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325752018&siteId=291194637