Artikel ini membawa anda pengetahuan yang berkaitan tentang python, yang terutamanya memperkenalkan isu yang berkaitan dengan kumpulan proses dan kunci proses, termasuk modul penciptaan kumpulan proses, fungsi kumpulan proses, dll. , mari kita lihat bersama-sama , saya harap ia akan membantu semua orang.
Pembelajaran yang disyorkan: tutorial video python
Kami menyebut isu tentang proses dalam bab sebelumnya Jika terlalu banyak proses dibuat, sumber akan digunakan terlalu banyak. Untuk mengelakkan keadaan ini, kita perlu menetapkan bilangan proses, dan pada masa ini kita memerlukan bantuan kumpulan proses.
Kita boleh menganggap kumpulan proses sebagai kumpulan di mana sejumlah proses tertentu dibuat terlebih dahulu. Lihat gambar di bawah:
Sebagai contoh, tatasusunan segi empat tepat merah ini mewakili kumpulan proses dan terdapat 6 proses dalam kumpulan ini. 6 proses ini akan dibuat bersama-sama dengan kumpulan proses Bukan itu sahaja, kami pernah berkata apabila mempelajari kitaran hayat berorientasikan objek bahawa setiap objek yang instantiated akan dikitar semula oleh pengurus memori selepas digunakan.
Proses kami juga akan dikitar semula oleh pengurus memori bersama-sama dengan proses penciptaan dan penutupan Ini adalah benar untuk setiap proses Proses yang dibuat apabila proses ditutup juga akan menggunakan jumlah prestasi tertentu. Proses dalam kumpulan proses tidak akan ditutup selepas ia dicipta, dan boleh digunakan semula sepanjang masa, dengan itu mengelakkan penggunaan sumber penciptaan dan penutupan, dan mengelakkan operasi berulang penciptaan dan penutupan, yang meningkatkan kecekapan.
Sudah tentu, apabila kita selesai melaksanakan program dan menutup kumpulan proses, proses itu juga akan ditutup.
Apabila kami mempunyai tugasan yang perlu dilaksanakan, kami akan menentukan sama ada terdapat sebarang proses terbiar dalam kumpulan proses semasa (yang dipanggil proses terbiar sebenarnya adalah proses dalam kumpulan proses yang tidak melaksanakan tugasan ). Apabila proses melahu, tugas akan mencari proses untuk melaksanakan tugas. Jika semua proses dalam kumpulan proses semasa berada dalam keadaan tidak melahu, tugasan akan memasuki keadaan menunggu Ia tidak akan masuk atau keluar dari kumpulan proses sehingga proses dalam kumpulan proses melahu untuk melaksanakan tugas.
Ini ialah peranan kumpulan proses.
函数名 | 介绍 | 参数 | 返回值 |
---|---|---|---|
Pool | 进程池的创建 | Processcount | 进程池对象 |
Pool功能介绍:通过调用 "multiprocessing" 模块的 "Pool" 函数来帮助我们创建 "进程池对象" ,它有一个参数 "Processcount" (一个整数),代表我们这个进程池中创建几个进程。
Selepas mencipta objek kumpulan proses, kita perlu mengendalikan prosesnya Mari kita lihat apakah kaedah (fungsi) biasa yang ada. .
函数名 | 介绍 | 参数 | 返回值 |
---|---|---|---|
apply_async | 任务加入进程池(异步) | func,args | 无 |
close | 关闭进程池 | 无 | 无 |
join | 等待进程池任务结束 | 无 | 无 |
- fungsi apply_async: Fungsinya adalah untuk menambah tugasan pada kumpulan proses dan dilaksanakan secara tak segerak.
异步
Kami belum mempelajari pengetahuan ini lagi, jadi jangan risau tentang maksudnya lagi. Ia mempunyai dua parameter:func 与 agrs
, func ialah fungsi yang ditambahkan pada kumpulan proses; args ialah tuple, mewakili parameter fungsi, yang betul-betul sama seperti semasa kita mencipta dan menggunakan proses.- fungsi tutup: Selepas kita selesai menggunakan kumpulan proses, kita boleh menutup kumpulan proses dengan memanggil fungsi tutup. Ia tidak mempunyai parameter dan tiada nilai pulangan.
- Fungsi Sertai: Ia selaras dengan fungsi gabungan yang kami pelajari dalam bab sebelumnya untuk mencipta proses. Hanya selepas semua tugasan dalam kumpulan proses dilaksanakan, tugasan seterusnya akan dilaksanakan. Walau bagaimanapun, ia biasanya digunakan apabila kumpulan proses ditutup (
close 函数
).
Seterusnya kami mencipta skrip dalam Pycharm untuk mempraktikkan penggunaan kumpulan proses.
- Tentukan fungsi dan cetak bilangan kali fungsi itu dilaksanakan setiap kali dan nombor proses untuk bilangan kali itu
- Tentukan bilangan kumpulan proses dan bilangan proses pelaksanaan setiap kali Bilangan maksimum proses yang ditetapkan untuk kumpulan proses
Kod sampel adalah seperti berikut:
# coding:utf-8import osimport timeimport multiprocessingdef work(count): # 定义一个 work 函数,打印输出 每次执行的次数 与 该次数的进程号 print('\'work\' 函数 第 {} 次执行,进程号为 {}'.format(count, os.getpid())) time.sleep(3) # print('********')if __name__ == '__main__': pool = multiprocessing.Pool(3) # 定义进程池的进程数量,同一时间每次执行最多3个进程 for i in range(21): pool.apply_async(func=work, args=(i,)) # 传入的参数是元组,因为我们只有一个 i 参数,所以我们要写成 args=(i,) time.sleep(15) # 这里的休眠时间是必须要加上的,否则我们的进程池还未运行,主进程就已经运行结束,对应的进程池也会关闭。
Hasil yang dijalankan adalah seperti berikut:
Daripada gambar di atas, kita dapat melihat bahawa tiga proses dijalankan serentak setiap kali Nombor proses setiap proses adalah berbeza, tetapi jika anda lihat dengan teliti, anda akan mendapati bahawa nombor proses yang sama wujud, yang menunjukkan bahawa ID proses kumpulan proses sedang digunakan semula. Ini membuktikan apa yang kami perkenalkan di atas, proses dalam kumpulan proses tidak akan ditutup dan boleh digunakan berulang kali.
Dan kami juga dapat melihat bahawa 3 proses dilaksanakan setiap 3 saat Sebabnya ialah hanya terdapat 3 proses dalam kumpulan proses kami; walaupun terdapat 21 tugas dalam for 循环
kami, fungsi kerja akan menjadi Dilaksanakan 21 kali, tetapi kerana kita hanya mempunyai 3 proses dalam kumpulan proses. Jadi selepas melaksanakan 3 tugasan (tidur selama 3 saat), tugasan seterusnya akan menunggu proses dalam kumpulan proses melahu sebelum meneruskan pelaksanaan.
Begitu juga, terdapat perbezaan tertentu dalam susunan nombor proses Sebabnya adalah kerana kami menggunakan kaedah 异步
(tak segerak atau tidak segerak). Ini menyebabkan ketiga-tiga tugasan work 函数
dilaksanakan bersama menjadi tidak teratur, itulah sebabnya nombor proses kami berada dalam susunan yang tidak konsisten. (更多的异步知识我们会在异步的章节进行详细介绍
)
进程池的原理: 上述脚本的案例证实了我们进程池关于进程的限制,只有当我们进程池中的进程处于空闲状态的时候才会将进程池外等待的任务扔到进程池中工作。
Dalam skrip di atas, kami menggunakan time.sleep(15)
membantu kami menyekat proses utama selama 15 saat dan keluar semula, sekali gus memberikan kumpulan proses kami masa yang mencukupi untuk menyelesaikan tugas gelung fungsi kerja() kami.
Bagaimana jika tiada ayat time.sleep(15)
sebenarnya, fungsi join
proses boleh digunakan di sini. Walau bagaimanapun, seperti yang kami nyatakan di atas, fungsi join()
sesuatu proses biasanya digunakan apabila kumpulan proses ditutup (close 函数
). Seterusnya, mari cuba gantikan time.sleep(15)
dalam skrip di atas dengan fungsi join()
.
Kod sampel adalah seperti berikut:
# coding:utf-8import osimport timeimport multiprocessingdef work(count): # 定义一个 work 函数,打印输出 每次执行的次数 与 该次数的进程号 print('\'work\' 函数 第 {} 次执行,进程号为 {}'.format(count, os.getpid())) time.sleep(3) # print('********')if __name__ == '__main__': pool = multiprocessing.Pool(3) # 定义进程池的进程数量,同一时间每次执行最多3个进程 for i in range(21): pool.apply_async(func=work, args=(i,)) # 传入的参数是元组,因为我们只有一个 i 参数,所以我们要写成 args=(i,) # time.sleep(15) pool.close() pool.join()
Hasil larian adalah seperti berikut:
Seperti yang kita boleh lihat daripada animasi di atas , tugasan fungsi work()
dan proses dalam kumpulan proses adalah konsisten dengan hasil penggunaan time.sleep(15)
.
PS: Jika proses utama kami akan sentiasa dilaksanakan, ia tidak akan keluar. Kemudian kita tidak perlu menambah close() 与 join() 函数
, kita boleh mengekalkan kumpulan proses bermula sehingga tugasan masuk dan ia akan dilaksanakan.
Selepas mempelajari pembangunan WEB kemudian, adalah perkara biasa untuk bekerja tanpa keluar dari proses utama. Terdapat juga beberapa tugasan yang perlu dilaksanakan dalam jangka masa yang lama dan tidak akan ditutup, tetapi jika hanya terdapat skrip pelaksanaan sekali sahaja, anda perlu menambah close() 与 join() 函数
untuk memastikan proses utama keluar selepas semua tugasan dalam kolam proses selesai. Sudah tentu, jika proses utama ditutup, ia tidak lagi menerima tugas baru, yang bermaksud berakhirnya kumpulan proses.
Mari lihat contoh lain, menambah pulangan dalam
work 函数
.Anda mungkin mempunyai soalan di sini Dalam bab sebelumnya, titik pengetahuan tentang proses tersebut dengan jelas disebut
进程无法获取返回值
, jadi apakah kepentinganwork()
yang ditambahkan pada fungsireturn
di sini?其实不然,在我们的使用进程池的
apply_async
方法时,是通过异步的方式实现的,而异步是可以获取返回值的。针对上述脚本,我们在for循环
中针对每一个异步apply_async
添加一个变量名,从而获取返回值。
示例代码如下:
# coding:utf-8import osimport timeimport multiprocessingdef work(count): # 定义一个 work 函数,打印输出 每次执行的次数 与 该次数的进程号 print('\'work\' 函数 第 {} 次执行,进程号为 {}'.format(count, os.getpid())) time.sleep(3) return '\'work\' 函数 result 返回值为:{}, 进程ID为:{}'.format(count, os.getpid())if __name__ == '__main__': pool = multiprocessing.Pool(3) # 定义进程池的进程数量,同一时间每次执行最多3个进程 results = [] for i in range(21): result = pool.apply_async(func=work, args=(i,)) # 传入的参数是元组,因为我们只有一个 i 参数,所以我们要写成 args=(i,) results.append(result) for result in results: print(result.get()) # 可以通过这个方式返回 apply_async 的返回值, # 通过这种方式也不再需要 使用 close()、join() 函数就可以正常执行。 # time.sleep(15) # 这里的休眠时间是必须要加上的,否则我们的进程池还未运行,主进程就已经运行结束,对应的进程池也会关闭。 # pool.close() # pool.join()
运行结果如下:
从运行结果可以看出,首先 work()
函数被线程池的线程执行了一遍,当第一组任务执行完毕紧接着执行第二次线程池任务的时候,打印输出了 apply_async
的返回值,证明返回值被成功的返回了。然后继续下一组的任务…
这些都是主要依赖于 异步
,关于 异步
的更多知识会在 异步
的章节进行详细的介绍。
锁:大家都知道,我们可以给一个大门上锁。
结合这个场景来举一个例子:比如现在有多个进程同时冲向一个 "大门"
,当前门内是没有 "人"的(其实就是进程),锁也没有锁上。当有一个进程进去之后并且把 “门” 锁上了,这时候门外的那些进程是进不来的。在门内的 “人” ,可以在 “门” 内做任何事情且不会被干扰。当它出来之后,会解开门锁。这时候又有一个 “人” 进去了门内,并且重复这样的操作,这就是 进程锁
。它可以让锁后面的工作只能被一个任务来处理,只有它解锁之后下一个任务才会进入,这就是 “锁” 的概念。
而 进程锁
就是仅针对于 进程
有效的锁,当进程的任务开始之后,就会被上一把 “锁”;与之对应的是 线程锁
,它们的原理几乎是一样的。
进程锁的使用方法:
通过 multiprocessing 导入 Manager 类
from multiprocessing import Manager
然后实例化 Manager
manager = Manager()
再然后通过实例化后的 manager 调用 它的 Lock() 函数
lock = manager.Lock()
接下来,就需要操作这个 lock 对象的函数
函数名 介绍 参数 返回值 acquire 上锁 无 无 release 解锁(开锁) 无 无
代码示例如下:
# coding:utf-8import osimport timeimport multiprocessingdef work(count, lock): # 定义一个 work 函数,打印输出 每次执行的次数 与 该次数的进程号,增加线程锁。 lock.acquire() # 上锁 print('\'work\' 函数 第 {} 次执行,进程号为 {}'.format(count, os.getpid())) time.sleep(3) lock.release() # 解锁 return '\'work\' 函数 result 返回值为:{}, 进程ID为:{}'.format(count, os.getpid())if __name__ == '__main__': pool = multiprocessing.Pool(3) # 定义进程池的进程数量,同一时间每次执行最多3个进程 manager = multiprocessing.Manager() lock = manager.Lock() results = [] for i in range(21): result = pool.apply_async(func=work, args=(i, lock)) # 传入的参数是元组,因为我们只有一个 i 参数,所以我们要写成 args=(i,) # results.append(result) # time.sleep(15) # 这里的休眠时间是必须要加上的,否则我们的进程池还未运行,主进程就已经运行结束,对应的进程池也会关闭。 pool.close() pool.join()
执行结果如下:
从上图中,可以看到每一次只有一个任务会被执行。由于每一个进程会被阻塞 3秒钟,所以我们的进程执行的非常慢。这是因为每一个进程进入到 work() 函数中,都会执行 上锁、阻塞3秒、解锁
的过程,这样就完成了一个进程的工作。下一个进程任务开始,重复这个过程… 这就是 进程锁的概念
。
其实进程锁还有很多种方法,在 multiprocessing
中有一个直接使用的锁,就是 ``from multiprocessing import Lock。这个
Lock的锁使用和我们刚刚介绍的
Manager` 的锁的使用有所区别。(这里不做详细介绍,感兴趣的话可以自行拓展一下。)
锁
的使用可以让我们对某个任务 在同一时间只能对一个进程进行开发,但是 锁也不可以乱用
。因为如果某些原因造成 锁没有正常解开
,就会造成死锁
的现象,这样就无法再进行操作了。
因为 锁如果解不开
,后面的任务也就没有办法继续执行任务,所以使用锁一定要谨慎。
推荐学习:python视频教程
Atas ialah kandungan terperinci Ketahui lebih lanjut tentang kumpulan proses Python dan kunci proses. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!