cuốn sách gpt4 ai đã làm

Triển khai đồng bộ hóa, các vấn đề về phần quan trọng, triển khai khóa và ngữ nghĩa

In lại Tác giả: Sahara Thời gian cập nhật: 25-12-2024 20:51:42 59 4
mua khóa gpt4 Nike

Khóa và chuyển đổi bối cảnh


Đồng thời

Nhiều nhiệm vụ được thực hiện trong cùng một khoảng thời gian, nhưng không nhất thiết phải cùng một lúc. Ví dụ, trên CPU lõi đơn, hệ điều hành đạt được khả năng xử lý đồng thời bằng cách chuyển đổi nhanh chóng các tác vụ.

Bổ sung: Tính song song, trong đó nhiều tác vụ thực sự chạy đồng thời, thường yêu cầu hỗ trợ CPU đa lõi, với mỗi lõi chạy một tác vụ cùng một lúc.

định luật Amdahl

Tăng tốc thông qua tính song song.

S=1/((1-P)+P/N).

P: Tỷ lệ các phần chương trình có thể song song hóa.

N: Số lượng bộ xử lý hoặc luồng thực thi được sử dụng bằng cách song song hóa.

Ví dụ

Nếu 95% chương trình có thể được song song hóa (bộ xử lý=4096), tốc độ tăng tốc tối đa theo lý thuyết là x20.

Đồng bộ hóa

Đảm bảo rằng các tiến trình hoặc luồng đồng thời không thực thi một số chương trình nhất định (Phần quan trọng) cùng một lúc.

Hai phương thức đồng bộ: Cạnh tranh và Phối hợp

Cuộc thi

Cạnh tranh một biến mà hai quá trình muốn đọc hoặc cập nhật đồng thời.

Phần quan trọng: Phần mã truy cập tài nguyên được chia sẻ.

Giải pháp là triển khai loại trừ lẫn nhau: Tại một thời điểm nhất định, chỉ một quy trình có thể chạy trong phần quan trọng.

Vậy làm thế nào để đạt được sự loại trừ lẫn nhau? (Xây dựng phần quan trọng).

Khóa.

Semaphores.

Màn hình.

Tin nhắn.

Điều kiện cuộc đua cần thiết để tạo ra sự cạnh tranh:

  • Một lỗi (ví dụ: bản cập nhật bị mất) xảy ra do nhiều quá trình 'đua nhau' một cách không được kiểm soát thông qua một phần mã phi nguyên tử.

  • Tình trạng chạy đua xảy ra khi đầu ra phụ thuộc vào thời gian hoặc trình tự của các sự kiện không được kiểm soát.

  • Xảy ra nếu nhiều luồng thực thi nhập các phần quan trọng của mã vào cùng một thời điểm và cả hai đều cố gắng cập nhật dữ liệu được chia sẻ.

Tiền gửi ngân hàng điển hình.

(Thực hiện LOCK):

Điểm mấu chốt: Tạo phương thức cập nhật public voidsynchronous update(){} của lớp ngân hàng.

lớp công khai Bank_account { riêng tư int bal = 0; công khai Bank_account(int start_balance) { bal = start_balance; } công khai void cập nhật được đồng bộ hóa (int money) { bal = bal + money; } } lớp công khai DepositTask triển khai tài khoản Bank_account riêng tư; int money; //Phương thức xây dựng public Mythread(Bank_account account,int money){ this.account=account; this.amount=amount; } public void run(){ account.updata(amount); } } public class main{ public static void main(String args[]){ Bank_accountbank=new Bank_account(100); DepositTask(bank,5); DepositTask task2=new DepositTask(bank,5); t2=Chủ đề mới(task2); t1.start; t2.start; thread1.join();
Phối hợp

Phối hợp: một quá trình muốn một quá trình khác có thể truy cập được kết quả cần thiết.

Ví dụ điển hình: vấn đề nhà sản xuất-người tiêu dùng (hộp sếp-nhân viên).

Chuyển đổi ngữ cảnh Chuyển đổi ngữ cảnh

Việc thực thi chuyển sang phần khác của bộ nhớ.

Ngữ cảnh của một luồng bao gồm: vị trí thực thi chương trình hoặc hàm + vị trí của chuỗi lệnh gọi hàm trong ngăn xếp.

  • Đặt vào chương trình (hoặc chức năng) mà luồng đang thực thi Vị trí nơi chương trình hoặc chức năng được thực thi.

  • Đặt vào ngăn xếp để ghi nhớ chuỗi các lệnh gọi hàm mà luồng đang thực hiện khi nó thực thi chương trình (mỗi luồng cần có ngăn xếp riêng).

Triển khai C: Bộ đếm chương trình (PC)+Con trỏ ngăn xếp (SP).

Ba bước để chuyển ngữ cảnh:

  • Hủy lịch trình luồng đang chạy –Lưu các thanh ghi PC và SP CPU của luồng đang chạy –Bắt buộc để luồng đó tiếp tục thực thi chính xác ở vị trí còn lại.

  • Bộ lập lịch chọn luồng sẵn sàng 'tốt nhất' để chạy tiếp theo –Cắt theo thời gian, mức độ ưu tiên, thiếu –Kiến trúc phần cứng, v.v. .

  • Khôi phục nội dung đăng ký trở lại thanh ghi PC & SP –Thread tiếp tục ở nơi nó dừng lại lần cuối (PC được tải lần cuối).

Semaphores Semaphore

Như đã đề cập trong phần trước, việc đồng bộ hóa có thể đạt được thông qua cạnh tranh và cạnh tranh là để xử lý việc loại trừ lẫn nhau các phần quan trọng (Phần quan trọng: các đoạn mã truy cập tài nguyên được chia sẻ) (Tại một thời điểm nhất định, chỉ một quy trình có thể chạy với phần quan trọng) . Có bốn cách để thực hiện loại trừ lẫn nhau: Khóa, ngữ nghĩa, giám sát và nhắn tin. Trong phần trên, Khóa được sử dụng để thực hiện vấn đề tiền gửi ngân hàng (chủ yếu sử dụng đồng bộ hóa). thực hiện loại trừ lẫn nhau.

Có ba thành phần quan trọng để triển khai một semaphore:

Bộ đếm (đại diện cho các tài nguyên có sẵn), .

wait()/P(): Giảm Bộ đếm đi 1. Nếu bộ đếm âm, điều đó có nghĩa là có một số quy trình đang chờ, thì đó là quy trình mà khối chỉ muốn nhập.

signal()/V(): Tăng Bộ đếm lên 1 (cho biết tài nguyên đã được giải phóng/một quy trình được nhập/có ít quy trình hơn trong hàng đợi).

Ví dụ điển hình: vấn đề gửi tiền ngân hàng, sử dụng semaphore.

public class Bank_account{ Private int bal=0; Private Semaphone mutex =1;//Sử dụng semaphores để đạt được sự loại trừ lẫn nhau chỉ một quá trình chạy trong phần quan trọng public void Bank_account(int Balance){ bal=balance } public void updata(int money) ){ mutex.wait(); bal=bal+số tiền;

Trên thực tế, Java đã giúp chúng ta tạo ra lớp semaphone. Chúng ta chỉ cần import java.util.concurrent.Semaphore để trực tiếp tạo một semaphore mới:

Tạo một semaphore --> Tạo một phiên bản có thể chạy được và đặt semaphore làm tham số ---> Tạo một phiên bản luồng và đặt nó vào phiên bản có thể chạy được.

import java.util.concurrent.Semaphore; public class SemaphoreExample { public static void main(String[] args) { // Tạo một semaphore, cho phép tối đa 1 thread truy cập Semaphore cùng lúc semaphore = new Semaphore(1); // Tạo nhiều thread truy cập cùng một tài nguyên for (int i = 1; i <= 5; i++) { Thread thread = new Thread(new Task(semaphore), "Thread-" + i); thread.start(); } } } // Xác định lớp nhiệm vụ Class thực hiện Runnable { semaphore riêng tư semaphore; run () { try { System.out.println(Thread.currentThread().getName() + " đang chờ giấy phép..."); semaphore.acquire(); // Nhận quyền System.out.println(Thread.currentThread().getName() + " đã có giấy phép!"); // Mô phỏng quyền truy cập tài nguyên Thread.sleep(2000); e) { e.printStackTrace(); } cuối cùng { System.out.println(Thread.currentThread().getName() + " sẽ phát hành allow..."); semaphore.release(); // Cấp phép phát hành} } }

ngữ nghĩa trong java

Tiếp theo, chúng ta hãy xem cách triển khai semaphore trong Java:

Tạo bộ đếm+tạo P+tạo V.

public class Semaphore { Private int count = 0; public Semaphore(int init_val) { count = init_val; //Bộ đếm ban đầu/số lượng tài nguyên/số tiến trình được phép truy cập khi được gọi} public được đồng bộ hóa void P() { count = count - 1; while (count < 0) wait(); // tại sao không dùng 'if'? để ngăn chặn sự đánh thức giả} được đồng bộ hóa công khai void V() { count = count + 1; một, đánh thức người phục vụ; */ if (count <= 0) notificationAll(); /*tại sao không sử dụng 'notify()' */ } }

Chúng ta cần chú ý đến những điểm sau:

  • Trong P, tại sao số lượng <0 yêu cầu chờ đợi? Vì số lượng nhỏ hơn 0 nên có nghĩa là có quá trình chờ trong hàng đợi, nên đương nhiên bạn cũng cần đợi. Nếu bộ đếm bằng hoặc lớn hơn 0 nghĩa là không có ai ở trước mặt bạn nên bạn có thể vào mà không cần chờ đợi.

  • Trong V, tại sao chỉ thông báo cho All khi đếm <= 0? Tương tự, có nghĩa là có hàng đợi nên cần thông báo. Nếu không có hàng chờ thì khi vào trực tiếp không cần thông báo.

  • while (count < 0) wait(); tại sao không sử dụng 'if'? Để ngăn chặn việc đánh thức sai + notificationAll được sử dụng trong mã.

  • 1.Để ngăn chặn sự đánh thức giả, 2. chúng tôi sử dụng notificationAll() trong P(). Trong trường hợp cạnh tranh đa luồng, while có thể đảm bảo rằng chỉ những luồng đáp ứng các điều kiện mới có thể tiếp tục thực thi và các luồng còn lại sẽ đợi lại .

  • thông báoAll() tại sao không thông báo? khái niệm thông báo + khái niệm thông báo Tất cả + nhược điểm của notfiy (những cái không đáp ứng các điều kiện sẽ được đánh thức và chuyển sang trạng thái chờ, những cái đáp ứng các điều kiện không thể được đánh thức + một số luồng bị chết đói).

  • 1. thông báo() Đánh thức một chuỗi đang chờ ngẫu nhiên 2. thông báoTất cả là đánh thức tất cả các chuỗi đang chờ 3. khi chúng ta sử dụng thông báo(), nó có thể đánh thức một chuỗi chưa sẵn sàng, trong khi chuỗi hài lòng không thể được đánh thức. up. Việc sử dụng notification() có thể khiến một số chủ đề bị chết đói.

Thức tỉnh giả

Đánh thức sai đề cập đến hiện tượng quá trình bị đánh thức bất ngờ khi luồng không đáp ứng các điều kiện và không nhận được thông báo rõ ràng (chẳng hạn như thông báo() hoặc thông báoAll()).

Sử dụng ngữ nghĩa để đạt được sự ngăn nắp (vấn đề giữa người sản xuất và người tiêu dùng)

Tài nguyên sẵn có ban đầu là 0 ---> nhà sản xuất tạo ra tài nguyên có sẵn (siganl()) ---> người tiêu dùng tiêu thụ tài nguyên (wait()).

Lấy ông chủ và nhân viên làm hộp làm ví dụ: ban đầu hộp trống -> sếp xác định kích thước hộp -> nhân viên lấy kích thước để làm hộp.

lớp công khai BoxDimension{ riêng tư int dim = 0; riêng tư Semaphore sem = 0; công khai void put(int d) {dim = d; //sem+1; ) { sem.wait();//sem-1; sem.P() return dim; 

Lưu ý: Lúc đầu, Semaphore sem =0, có nghĩa là không có tài nguyên; trước tiên, ông chủ xác định kích thước và sau đó đánh dấu các tài nguyên có sẵn +1 và thông báo cho nhân viên trước xem họ có thể truy cập tài nguyên hay không và sau đó trả về dim.

Cuối cùng, bài viết này về việc triển khai đồng bộ hóa, các vấn đề về phần quan trọng, khóa và ngữ nghĩa có ở đây. Nếu bạn muốn biết thêm về việc triển khai đồng bộ hóa, các vấn đề về phần quan trọng, khóa và ngữ nghĩa, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt qua 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! .

59 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress