Sử dụng đồng bộ - 1

"Chào, Amigo!"

"Ừ, tôi ở đây, tôi ở đây."

"Hôm nay, tôi sẽ cho bạn biết về việc sử dụng đồng bộ hóa trong thực tế."

"Khi một chương trình có nhiều đối tượng và luồng, thường xảy ra trường hợp nhiều luồng hoạt động đồng thời với cùng một đối tượng. Khi làm như vậy, các luồng sẽ can thiệp lẫn nhau."

"Vâng, tôi đã biết điều này."

"Vì vậy, giả sử bạn có một đối tượng được truy cập bởi nhiều luồng. Bạn có thể làm hai việc để tránh sự cố."

"Đầu tiên là sử dụng các khối được đồng bộ hóa để bọc mọi vị trí mà đối tượng được truy cập. Nhưng cách tiếp cận này có thể không hoạt động nếu một số lập trình viên viết mã truy cập trực tiếp vào đối tượng mà không có khối được đồng bộ hóa."

"Do đó, cách tiếp cận thứ hai được sử dụng hầu hết thời gian—làm cho đối tượng trở nên an toàn." "Nói cách khác, cơ chế đồng bộ hóa được tích hợp vào chính đối tượng: nó tuyên bố các phương thức của nó được đồng bộ hóa và/hoặc bao bọc mã bên trong các phương thức của nó trong các khối được đồng bộ hóa."

"Vì vậy, bất kỳ đối tượng nào mà tôi có thể sử dụng từ nhiều luồng và đây là hầu hết tất cả các đối tượng trong chương trình, tôi phải tạo luồng an toàn?"

"Nói chung là có. Trong thực tế, không phải tất cả các đối tượng trong một chương trình đều được sử dụng bởi các luồng khác nhau, nhưng thường có rất nhiều. Vì vậy, khi bạn bắt đầu viết mã cho một luồng và truy cập các đối tượng khác nhau từ đó, thì với mỗi lệnh gọi phương thức bạn nên tự hỏi mình, «Cuộc gọi này có an toàn không?»"

"An toàn?"

"Thread-safe, có nghĩa là nó có thể được gọi một cách an toàn từ nhiều luồng."

"Dưới đây là một số ví dụ. Giả sử bạn có một đối tượng Chuỗi được truy cập từ các luồng khác nhau. Như bạn đã phải nhớ, Chuỗi là bất biến —cũng như tất cả các kiểu nguyên thủy khác. Điều này có nghĩa là một đối tượng không thay đổi sau khi nó được tạo . Điều này có nghĩa là không thể «phá vỡ» một đối tượng như vậy. Tất cả các đối tượng bất biến đều an toàn cho luồng."

"Chà, điều đó làm cho mọi thứ dễ dàng hơn."

"Bây giờ, giả sử bạn cần một chuỗi có thể thay đổi."

"Vâng, tôi nhớ. Có hai loại chuỗi như vậy: StringBuffer và StringBuilder. StringBuffer giống như StringBuilder, nhưng tất cả các phương thức của nó đều được đồng bộ hóa. Nó cũng an toàn cho chuỗi chứ?"

"Phải. Nếu bạn cần truy cập một đối tượng StringBuilder từ nhiều luồng, bạn phải thay thế nó bằng một StringBuffer. Nếu không, sớm hay muộn các luồng sẽ thay đổi nó cùng một lúc và «phá vỡ» nó."

"Điều gì sẽ xảy ra nếu đối tượng được truy cập từ các luồng khác nhau là một đối tượng thuộc lớp của tôi? Tôi có cần thêm đồng bộ hóa vào các phương thức của nó trong trường hợp này không?"

"Có. Tốt nhất là tuân theo quy tắc này: tất cả các đối tượng sẽ được truy cập từ các luồng khác nhau phải an toàn cho luồng."

"Tôi hiểu rồi. Tôi không nghĩ mọi chuyện lại nghiêm trọng như vậy. Cảm ơn, Ellie."

"Không có gì. Tôi hy vọng những lời khuyên này sẽ giúp ích cho bạn khi Diego giao cho bạn một vài nhiệm vụ dễ dàng của anh ấy. ☺"