sách gpt4 ai đã đi

Giải thích chi tiết về cách sử dụng đơn giản của đa luồng Python, khóa và cơ chế sự kiện

In lại Tác giả:qq735679552 Thời gian cập nhật: 2022-09-28 22:32:09 29 4
mua khóa gpt4 Nike

CFSDN nhấn mạnh vào việc tạo ra giá trị thông qua mã nguồn mở. Chúng tôi cam kết xây dựng một nền tảng chia sẻ tài nguyên để mọi người làm CNTT có thể tìm thấy thế giới tuyệt vời của riêng mình tại đây.

Bài đăng trên blog CFSDN này giải thích cách sử dụng đơn giản của Python multithreading, locks và event mechanism. Bài viết được tác giả thu thập và sắp xếp. Nếu bạn quan tâm đến bài viết này, hãy nhớ thích nó.

Luồng và tiến trình.

1. Luồng chia sẻ không gian địa chỉ của tiến trình đã tạo ra nó và tiến trình có không gian địa chỉ riêng.

2. Luồng có thể truy cập tất cả dữ liệu của tiến trình và các luồng có thể truy cập lẫn nhau.

3. Dữ liệu giữa các luồng là độc lập.

4. Tiến trình con sao chép dữ liệu của luồng.

5. Sau khi tiến trình con được khởi động, nó độc lập. Tiến trình cha chỉ có thể giết tiến trình con nhưng không thể trao đổi dữ liệu.

6. Việc sửa đổi dữ liệu trong một luồng sẽ ảnh hưởng đến các luồng khác, nhưng những thay đổi trong tiến trình sẽ không ảnh hưởng đến tiến trình con.

luồng. Chủ đề.

Thread là một trong những lớp quan trọng nhất trong mô-đun threading, có thể được sử dụng để tạo luồng. Có hai cách để tạo một luồng: một là kế thừa lớp Thread và ghi đè phương thức chạy của nó; cách khác là tạo một đối tượng threading.Thread và truyền đối tượng có thể gọi được làm tham số trong hàm khởi tạo của nó (__init__). Trước tiên chúng ta hãy xem ví dụ về việc tạo luồng bằng cách kế thừa lớp threading.Thread:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nhập khẩu xâu chuỗi
nhập khẩu thời gian
 
lớp học MyThread(threading.Thread):
  định nghĩa __khởi tạo__( bản thân , tranh luận):
   # super(MyThread, self).__init__() # Lớp kiểu mới kế thừa phương thức viết phương thức gốc
   luồng.Thread.__init__( bản thân )
   bản thân .đối số = tranh luận
 
  định nghĩa chạy( bản thân ):
   thời gian.ngủ( 2 )
   in ( bản thân .arg)
 
Tôi TRONG phạm vi ( 10 ):
  chủ đề = MyThread(i)
  in (tên luồng)
  thread.bắt đầu()

Một cách khác để tạo chủ đề:

?
1
2
3
4
5
6
7
8
9
10
11
nhập khẩu xâu chuỗi
nhập khẩu thời gian
 
định nghĩa tiến trình(đối số):
  thời gian.ngủ( 2 )
  in (tranh luận)
 
Tôi TRONG phạm vi ( 10 ):
  t = luồng.Thread(mục tiêu = quá trình, đối số = (Tôi,))
  in (tên.t.name)
  t.bắt đầu()

Lớp Thread cũng định nghĩa các phương thức và thuộc tính chung sau:

Thread.getName() Lấy tên luồng.

Thread.setName() đặt tên luồng.

Thread.name Tên chủ đề.

Thread.ident Lấy mã định danh của luồng. Mã định danh luồng là một số nguyên khác không và chỉ hợp lệ sau khi phương thức start() được gọi; nếu không, nó sẽ trả về None.

Xác định xem luồng có hoạt động hay không. Luồng hoạt động từ thời điểm phương thức start() được gọi để bắt đầu luồng cho đến thời điểm phương thức run() được thực thi hoặc bị gián đoạn bởi một ngoại lệ chưa được xử lý.

Thread.is_alive() .

Thread.join([timeout]) Việc gọi Thread.join sẽ chặn luồng gọi cho đến khi luồng được gọi chạy xong hoặc hết thời gian chờ. Tham số timeout là một kiểu số, biểu thị khoảng thời gian chờ. Nếu tham số này không được cung cấp, luồng gọi sẽ bị chặn cho đến khi luồng được gọi kết thúc.

Python GIL (Khóa thông dịch toàn cục).

GIL không phải là một tính năng của Python, mà là một khái niệm được giới thiệu khi triển khai trình thông dịch Python (CPython). Giống như C++ là một tập hợp các tiêu chuẩn ngôn ngữ (cú pháp), nhưng nó có thể được biên dịch thành mã thực thi bằng các trình biên dịch khác nhau. Các trình biên dịch nổi tiếng bao gồm GCC, INTEL C++, Visual C++, v.v. Điều này cũng đúng với Python. Cùng một đoạn mã có thể được thực thi bởi các môi trường thực thi Python khác nhau như CPython, PyPy, Psyco, v.v. Ví dụ, JPython không có GIL. Tuy nhiên, vì CPython là môi trường thực thi Python mặc định trong hầu hết các môi trường. Do đó, trong suy nghĩ của nhiều người, CPython chính là Python và họ tự nhiên cho rằng GIL là một khiếm khuyết của ngôn ngữ Python. Vì vậy, trước tiên chúng ta phải làm rõ một điều: GIL không phải là một tính năng của Python, Python có thể hoàn toàn độc lập với GIL.

Sử dụng khóa ren:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Khóa: Trình thông dịch toàn cục GIL là để đảm bảo rằng luồng không bị chiếm dụng trong quá trình thực thi
con số = 0
khóa = luồng.RLock() # Tạo khóa
 
 
định nghĩa chạy(số):
  khóa.thu thập() # Khóa
  toàn cầu con số
  con số + = 1
  in (con số)
  thời gian.ngủ( 2 )
  khóa.phát hành() # Mở khóa
 
Tôi TRONG phạm vi ( 10 ):
  t = luồng.Thread(mục tiêu = chạy, args = (Tôi, ))
  t.bắt đầu()

Tham gia & Daemon.

Trong luồng chính A, một luồng con B được tạo ra và B.setDaemon() được gọi trong luồng chính A. Điều này có nghĩa là luồng chính A được đặt thành luồng daemon. Vào thời điểm này, nếu luồng chính A hoàn tất việc thực thi, bất kể luồng con B có hoàn tất hay không, nó sẽ thoát cùng với luồng chính A. Đây là ý nghĩa của phương thức setDaemon, về cơ bản là ngược lại với join. Ngoài ra, có một điều cần đặc biệt chú ý: nó phải được thiết lập trước khi phương thức start() được gọi. Nếu nó không được thiết lập như một luồng daemon, chương trình sẽ bị treo vô thời hạn.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lớp học MyThread1(threading.Thread):
  định nghĩa __khởi tạo__( bản thân ):
   luồng.Thread.__init__( bản thân )
 
  định nghĩa chạy( bản thân ):
   in ( "bắt đầu chủ đề" )
   thời gian.ngủ( 3 )
   in ( 'kết thúc chủ đề' )
 
in ( 'khởi đầu chính' )
chủ đề1 = Chủ đề của tôi1()
# thread1.setDaemon(True) # Thiết lập xem luồng con có kết thúc bằng luồng chính không
thread1.bắt đầu()
thời gian.ngủ( 1 )
in ( 'tham gia satrt' )
# thread1.join() # Chặn luồng chính cho đến khi luồng con chạy xong và sau đó tiếp tục luồng chính
in ( 'kết thúc tham gia' )
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
định nghĩa chạy(n):
  in ( '[%s]------đang chạy----\n' % N)
  thời gian.ngủ( 2 )
  in ( '--xong--' )
 
 
định nghĩa chủ yếu():
  Tôi TRONG phạm vi ( 5 ):
   t = luồng.Thread(mục tiêu = chạy, args = [Tôi,])
   t.bắt đầu()
   # t.tham gia()
   in ( 'chủ đề bắt đầu' , t.getName())
 
 
tôi = luồng.Thread(mục tiêu = chính,đối số = [])
# m.setDaemon(True) # Đặt luồng chính thành luồng Daemon. Khi luồng này thoát, các luồng con khác sẽ thoát cùng lúc, bất kể tác vụ có hoàn thành hay không.
m.bắt đầu()
# m.join() # Chặn luồng chính cho đến khi luồng con chạy xong và sau đó tiếp tục luồng chính
in ( "---chủ đề chính đã xong-----" )

Khóa luồng (mutex).

Nhiều luồng có thể được khởi động dưới một tiến trình, và nhiều luồng chia sẻ không gian bộ nhớ của tiến trình cha, điều này có nghĩa là mỗi luồng có thể truy cập cùng một dữ liệu. Lúc này, nếu hai luồng muốn sửa đổi cùng một dữ liệu cùng một lúc, điều gì sẽ xảy ra?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
số = 100 # Đặt biến chia sẻ
định nghĩa số phụ():
  toàn cầu số # Nhận biến toàn cục này trong mỗi luồng
  in ( '--lấy số:' , số)
  thời gian.ngủ( 2 )
  số - = 1 # Thực hiện phép toán -1 trên biến công khai này
danh sách chủ đề = []
Tôi TRONG phạm vi ( 100 ):
  t = luồng.Thread(mục tiêu = Số phụ)
  t.bắt đầu()
  thread_list.append(t)
t TRONG danh sách chủ đề: # Chờ tất cả các luồng hoàn tất việc thực thi
  t.tham gia()
in ( 'số cuối cùng:' , số)
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Phiên bản bị khóa
định nghĩa số phụ():
  toàn cầu số # Nhận biến toàn cục này trong mỗi luồng
  in ( '--lấy số:' , số)
  thời gian.ngủ( 1 )
  khóa.thu thập() # Khóa trước khi sửa đổi dữ liệu
  số - = 1 # Thực hiện phép toán -1 trên biến công khai này
  khóa.phát hành() # Phát hành sau khi sửa đổi
 
số = 100 # Đặt biến chia sẻ
danh sách chủ đề = []
khóa = luồng.Khóa() # Tạo khóa toàn cục
Tôi TRONG phạm vi ( 100 ):
  t = luồng.Thread(mục tiêu = Số phụ)
  t.bắt đầu()
  thread_list.append(t)
t TRONG danh sách chủ đề: # Chờ tất cả các luồng hoàn tất việc thực thi
  t.tham gia()
in ( 'số cuối cùng:' , số)

Sự khác biệt giữa Rlock và Lock:

RLock cho phép lấy được nhiều lần trong cùng một luồng. Khóa không cho phép điều này. Nếu không, vòng lặp vô hạn sẽ xảy ra và chương trình sẽ không biết phải mở khóa nào. Lưu ý: Nếu sử dụng RLock, acquire và release phải xuất hiện theo cặp, nghĩa là nếu acquire được gọi n lần, release phải được gọi n lần để thực sự giải phóng khóa đang chiếm giữ.

Sự kiện.

Python cung cấp đối tượng Sự kiện cho giao tiếp giữa các luồng, là cờ tín hiệu do luồng thiết lập. Nếu cờ tín hiệu là đúng, các luồng khác sẽ đợi cho đến khi tín hiệu được liên lạc. Đối tượng Sự kiện triển khai cơ chế giao tiếp luồng đơn giản, cung cấp các chức năng như thiết lập tín hiệu, xóa tín hiệu và chờ giao tiếp giữa các luồng.

event = threading.Event() tạo ra một sự kiện.

1 Đặt tín hiệu event.set().

Sử dụng phương thức set() của Event để đặt cờ tín hiệu bên trong đối tượng Event thành true. Đối tượng Sự kiện cung cấp phương thức isSet() để xác định trạng thái của cờ tín hiệu bên trong của nó. Khi phương thức set() của đối tượng sự kiện được sử dụng, phương thức isSet() trả về true.

2 Xóa sự kiện tín hiệu.clear().

Phương thức clear() của đối tượng Event có thể được sử dụng để xóa cờ tín hiệu bên trong đối tượng Event, tức là đặt cờ tín hiệu thành false. Sau khi sử dụng phương thức clear() của Event, phương thức isSet() trả về false.

3 Chờ với event.wait() .

Phương thức wait của đối tượng Event sẽ thực thi và trả về nhanh chóng chỉ khi tín hiệu bên trong là đúng. Khi cờ tín hiệu bên trong của đối tượng Sự kiện là sai, phương thức wait sẽ đợi cho đến khi nó trở thành đúng trước khi trả về. Nghĩa là, cờ số mới phải được đặt thành đúng.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
định nghĩa làm(sự kiện):
  in ( 'bắt đầu' )
  sự kiện.chờ()
  in ( 'thực hiện' )
 
sự kiện_obj = luồng.Sự kiện()
Tôi TRONG phạm vi ( 10 ):
  t = luồng.Thread(mục tiêu = làm, tranh luận = (sự kiện_đối tượng,))
  t.bắt đầu()
 
event_obj.xóa()
vào = đầu vào ( 'Nhập nội dung:' )
nếu như vào = = 'ĐÚNG VẬY' :
  sự kiện_đối tượng. bộ ()

Trên đây là toàn bộ nội dung bài viết này, hy vọng sẽ giúp ích cho việc học tập của mọi người, và mong các bạn ủng hộ tôi.

Liên kết gốc: https://segmentfault.com/a/1190000014619654.

Cuối cùng, bài viết này về giải thích chi tiết về cách sử dụng đơn giản của Python đa luồng, khóa và cơ chế sự kiện kết thúc tại đây. Nếu bạn muốn biết thêm về giải thích chi tiết về cách sử dụng đơn giản của Python đa luồng, khóa và cơ chế sự kiện, vui lòng tìm kiếm các bài viết CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .

29 4 0
qq735679552
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com