11. Đồng bộ hóa
11.1 Phát thông điệp và đợi
Ở bài học trước, bạn đã được làm quen với lệnh broadcast message để phát một thông báo (thông điệp). Khi thông báo được phát ra, mọi đối tượng nhận được thông báo sẽ đồng loạt thực thi. Cụ thể, khi Nhạc trưởng thông báo là bắt đầu biểu diễn thì ca sĩ, nhạc công, múa phụ họa, mạnh ai người đó biểu diễn, loạn cả sân khấu.
Trong lập trình đôi khi bạn không được để tình trạng này xảy ra, các đối tượng cần được thực thi một cách tuần tự, hết việc trước rồi mới đến việc sau.
Để các công việc được thực hiện một cách có tuần tự, chúng ta sẽ sử dụng khối lệnh broadcast and wait (thông báo và đợi).
Khối lệnh broadcast and wait sẽ phát ra thông điệp, và sẽ chờ tới khi nào tất cả các thông điệp đều được thực thi, thì người phát thông điệp mới được gửi thông điệp tiếp theo.
Chúng ta cùng làm một ví dụ để so sánh sự khác nhau giữa khối lệnh [broadcast message] và [broadcast message and wait].
Chúng ta cùng lập trình.
Trường hợp 1. Chưa có bánh mà đã báo có rồi
Tạo 3 nhân vật: đầu bếp, lò nướng và khách hàng.
- Đầu bếp sẽ phát thông điệp [làm pizza].
- Lò nướng nhận thông điệp [làm pizza], sẽ chờ 5 giây và nói “pizza đã nướng xong”.
- Khách hàng nhận thông điệp [làm pizza], sẽ nói “đang đợi pizza”
Khi dùng khối lệnh broadcast message (bạn sẽ làm để hiểu sự không hợp lý khi chạy chương trình.
Lập trình cho nhân vật Đầu bếp (đặt tên là DauBep)
(đầu bếp chỉ biết làm công việc của mình mà không chờ đợi kết quả xử lý của các đối tượng khác)
Lập trình cho nhân vật Lò nướng (đặt tên là LoNuong)
Lập trình cho nhân vật Khách hàng (đặt tên là KhachHang)
Khi chạy chương trình, bạn sẽ sẽ thấy:
- Đầu bếp gửi thông điệp [làm pizza]
- Cả Lò nướng và Khách hàng đồng thời nhận và thực thi lệnh
- Đầu bếp nói "Đã có pizza cho khách rồi nha." ngay lập tức (vì không chờ đợi)
- Khách hàng nói "Đang đợi pizza..." cũng gần như ngay lập tức
- Lò nướng mất 5 giây để nướng
- Khách hàng và Đầu bếp đã kết thúc câu nói của mình rất lâu trước khi Lò nướng nói "Pizza đã nướng xong!"
Bạn đã thấy: Mọi thứ chạy lộn xộn/đồng thời, Khách hàng/Đầu bếp đã thực thi xong, trong khi pizza còn chưa nướng xong.
Trường hợp 2. Sửa lại mã lập trình để chương trình chạy hợp lý hơn
Bây giờ, chúng ta sẽ thay đổi một khối lệnh duy nhất của Đầu bếp để buộc Đầu bếp phải chờ Lò nướng (và các nhân vật khác) phải hoàn thành công việc thì mới được nói câu tiếp theo (được làm các việc tiếp theo).
- Giữ nguyên đoạn mã của Lò nướng và Khách hàng
- Sửa đoạn mã cho Đầu bếp
Khi chạy chương trình, bạn sẽ thấy một trình tự thực thi hợp lý hơn:
- Đầu bếp gửi thông điệp [làm pizza] và ĐỨNG IM (tạm dừng)
- Lò nướng và Khách hàng thực thi lệnh đồng thời (nhưng Đầu bếp vẫn đang chờ)
- Khách hàng nói "Đang đợi pizza..." (4 giây)
- Lò nướng đợi 5 giây và nói "Pizza đã nướng xong!"
- Chỉ sau khi Lò nướng hoàn thành (kết thúc lệnh chờ 5 giây), Đầu bếp mới tiếp tục kịch bản và nói "Đã có pizza cho khách rồi nha"
Trên đây là để làm rõ sự khác biệt giữa hai khối lệnh broadcast và broadcast and wait trong việc kiểm soát trình tự thời gian.
- Khối lệnh "broadcast" cho phép các lệnh chạy đồng thời (cùng một lúc)
- Khối lệnh "broadcast and wait" buộc các lệnh phải chạy tuần tự (lần lượt)
11.1 Broadcast and wait
The broadcast and wait block waits until the last message has been finished. Here we see the first stack finished and the second stack still being executed.
11.2 Bài tập
Bài tập 11a. Cuộc thi chạy marathon
Tình huống: Trong khu rừng tổ chức một cuộc thi chạy marathon tốc độ. Người dẫn chương trình (MC) cần đảm bảo “Tất cả vận động viên đều phải có mặt và sẵn sàng” trước khi phát lệnh xuất phát. Rùa là vận động viên luôn chậm nhất và cần nhiều thời gian để "khởi động" nhất.
Mục tiêu bài tập
Sử dụng khối lệnh "broadcast and wait" để đảm bảo MC chỉ hô khẩu hiệu "Bắt đầu!" sau khi nhân vật Rùa đã hoàn thành công đoạn chuẩn bị của mình.
Các bước thực hiện
1. Thiết lập nhân vật
Tạo ba nhân vật (sprites):
- MC: Người điều khiển cuộc thi
- Thỏ (rabbit): vận động viên nhanh
- Rùa (turtle): vận động viên chậm
2. Lập trình cho nhân vật Rùa (turtle)
Rùa cần thời gian lâu nhất để "khởi động."
3. Lập trình cho nhân vật Thỏ (rabbit)
Thỏ luôn nhanh, chỉ cần chuẩn bị trong thời gian ngắn.
4. Lập trình cho nhân vật MC (Người dẫn chương trình)
MC cần gửi lệnh chuẩn bị và buộc phải chờ cho đến khi Rùa và Thỏ đều xong xuôi.
Yêu cầu Bài tập
1. Bạn hãy điền khối lệnh chính xác vào ô [KHỐI LỆNH CẦN ĐIỀN] của nhân vật MC để đảm bảo câu nói "Bắt đầu! Chạy thôi!" chỉ xuất hiện sau khi Rùa đã nói "Rùa đã sẵn sàng!".
2. Sau khi điền, hãy chạy chương trình và mô tả lại trình tự xuất hiện lời thoại của 3 nhân vật.