Ví dụ cụ thể
Tôi muốn thêm một số ví dụ trong thế giới thực và kết nối chúng với thế giới công nghệ phần mềm. Trước tiên, hãy xem xét một cái gì đó mà tôi hy vọng phù hợp với định nghĩa trực quan của bạn về "đồng bộ": nhấp nháy của đom đóm , trong một số trường hợp. Thứ hai, hãy xem xét cuộc đua tiếp sức Olympic 4x100 của phụ nữ . Thứ ba, hãy xem xét trope cũ từ các bộ phim quân sự: "Đàn ông, đồng bộ hóa đồng hồ của bạn!"
Bây giờ, hãy nghĩ về những gì đang xảy ra. Hãy bắt đầu bằng cách quan sát rằng tất cả những điều này là các quá trình hoặc các thực thể được kéo dài theo thời gian . Thật vô nghĩa khi nói rằng một cái bát là "đồng bộ" và rock là "không đồng bộ". Thứ hai, phải mất hai đến tango . Bạn không thể nói rằng "một người chạy là đồng bộ hóa". Đồng bộ hóa với cái gì? Cuối cùng, để hai quá trình thực hiện cùng một lúc, trừ khi chúng có cùng tần số và pha chính xác, một hoặc cả hai quá trình phải chờ .
Phân tích
Khi định nghĩa từ điển nói rằng hai thực thể đồng bộ "xảy ra hoặc tồn tại cùng một lúc", điều đó rất phù hợp với khái niệm ánh sáng từ đom đóm. Thật không may, nói rằng ánh sáng là "đồng bộ" là một cách cẩu thả để nói rằng các quy trình chiếu sáng đom đóm được đồng bộ hóa.
Vậy làm thế nào để một đàn đom đóm, có lẽ không có Apple SmartWatch và NTP để hướng dẫn chúng, quản lý để nháy đèn hậu của chúng cùng một lúc? Chà, thật dễ dàng nếu họ có một phương tiện để đặt nhịp độ nhất quán và có thể thực hiện những điều chỉnh nhỏ cho nó. Chúng chỉ flash, và nếu nhiều người hơn flash ngay sau chúng, chúng sẽ chậm lại (tăng độ trễ), trong khi nếu nhiều flash hơn ngay trước chúng, chúng sẽ tăng tốc (giảm độ trễ). Vì vậy, họ có thể sử dụng một quá trình phản hồi đơn giản để đến cơ bản cùng một nhịp độ và giai đoạn. Quan sát quan trọng ở đây là lưu ý rằng họ đạt được sự đồng bộ bằng cách chờ đợi thời điểm thích hợp để flash .
Cuộc đua 4x100 rất thú vị bởi vì bạn thấy cả hai hình thức xử lý thời gian hoạt động: các vận động viên trong một nhóm được đồng bộ hóa, trong khi các vận động viên trên các đội khác nhau là " không đồng bộ ". Người chạy thứ hai trong rơle phải đợi cho đến khi người chạy thứ nhất vào khu vực chuyển nhượng . Việc bắt tay là một sự kiện đồng bộ giữa hai vận động viên đó. Tuy nhiên, những người chạy ở các làn đường khác nhau không quan tâm đến những gì đang xảy ra ở một làn đường khác , và chắc chắn là không làm chậm và thực hiện đồng bộ hóa tay của họ. Mỗi làn của người chạy là không đồng bộ với nhau. Một lần nữa, chúng ta thấy rằng đồng bộ hóa đòi hỏi phải chờ đợi, trong khi không đồng bộ hóa thì không.
Cuối cùng, những người lính trong một đại đội (trung đội, đội cứu hỏa, v.v.) phải đồng bộ hóa đồng hồ của họ để có thể tấn công kẻ thù cùng một lúc . Nó có thể là một số binh sĩ đến vị trí của họ trước những người khác, hoặc có cơ hội bắn vào kẻ thù sớm hơn. Nhưng một cuộc tấn công đồng thời thường hiệu quả hơn một cuộc tấn công ngớ ngẩn vì yếu tố bất ngờ. Vì vậy, để đạt được sự đồng bộ, nhiều người lính phải chờ thời gian chỉ định để hành động.
Xác định tính năng
Tại sao điều này nhấn mạnh vào sự chờ đợi? Vâng, đó là bởi vì chờ đợi là tính năng xác định phân biệt đồng bộ với các quy trình không đồng bộ. Nếu bạn có hai quy trình mà bạn không biết gì về nó, theo mặc định, bạn nên cho rằng chúng không đồng bộ. Ví dụ: giao hàng trọn gói và lái xe cứu thương rất có thể không được đồng bộ hóa. Trên thực tế, để chứng minh rằng hai quá trình được đồng bộ hóa, bạn cần tìm một thời điểm rất đặc biệt: thời điểm đồng bộ hóa .
Một tài xế giao hàng thả gói hàng và xe cứu thương đưa ai đó đến bệnh viện thường không chia sẻ bất kỳ điểm nào mà chúng tôi xác định là "điểm đồng bộ hóa". Mặt khác, những con đom đóm nhấp nháy đồng loạt có một điểm đồng bộ mỗi khi chúng nhấp nháy, những người chạy tiếp sức có một điểm đồng bộ mỗi khi họ cầm dùi cui và binh lính có một điểm đồng bộ khi họ phát động cuộc tấn công. Nếu bạn có thể xác định một hoặc nhiều điểm đồng bộ hóa, thì các quy trình được đồng bộ hóa . Điều này nên dễ hiểu, bởi vì "syn-" là tiền tố Hy Lạp có nghĩa là "với" hoặc "cùng nhau" và "chrono" là từ gốc Hy Lạp cho "thời gian". "Đồng bộ hóa" nghĩa đen là "cùng một lúc",
Ranh giới
Lưu ý rằng "đồng bộ hóa" không nhất thiết phải áp dụng cho toàn bộ vòng đời của một hoặc cả hai quá trình. Tôi sẽ lập luận rằng nó chỉ áp dụng cho "thời gian chờ lên đến và bao gồm (các) điểm đồng bộ hóa". Do đó, hai quy trình có thể hoạt động không đồng bộ cho đến khi chúng đạt đến trạng thái cần liên lạc, sau đó chúng được đồng bộ hóa, trao đổi thông tin và sau đó tiếp tục không đồng bộ. Một ví dụ đơn giản là gặp ai đó để uống cà phê. Rõ ràng, cuộc họp là một điểm đồng bộ hóa (hoặc nhiều hơn, đúng hơn), và thực tế là hai người đến điểm đó thể hiện sự đồng bộ. Tuy nhiên, chúng tôi sẽ không nói rằng vì hai người gặp nhau vì cà phê, hai kiếp người đóđược "đồng bộ hóa". Có thể đó là khoảnh khắc duy nhất trong cuộc sống của họ mà họ gặp, và mọi thứ khác họ làm đều độc lập.
Nó cũng không phải là trường hợp ngẫu nhiên đáp ứng chứng minh sự đồng bộ. Nếu hai người lạ gặp nhau trên đường phố, thực tế là họ đang ở một nơi cụ thể vào một lúc nào đó không chứng minh được sự đồng bộ. Thực tế là một người đang ngồi trên băng ghế chờ xe buýt, và một người khác tình cờ đi ngang qua. Các quy trình chỉ đồng bộ khi chúng đáp ứng cho một mục đích .
Kết nối phần mềm
Bây giờ, hãy nghĩ về một nhiệm vụ rất cơ bản trong phần mềm: đọc từ một tệp. Như bạn có thể biết, lưu trữ dung lượng lớn thường chậm hơn hàng nghìn đến hàng triệu lần so với bộ nhớ cache hoặc bộ nhớ chính. Vì lý do này, các hệ điều hành và thư viện ngôn ngữ lập trình thường cung cấp cả hoạt động I / O đồng bộ và không đồng bộ. Bây giờ, ngay cả khi chương trình của bạn chỉ có một luồng duy nhất, bạn nên nghĩ HĐH là một "quy trình riêng" cho mục đích thảo luận này.
Đồng bộ hóa
Khi bạn thực hiện "đọc I / O đồng bộ", luồng của bạn phải đợi cho đến khi dữ liệu có sẵn, tại thời điểm đó nó tiếp tục. Điều này rất giống với một vận động viên chạy tiếp sức đưa cây dùi cui cho người chạy tiếp theo, nhưng hãy tưởng tượng thay vào đó là một cuộc tiếp sức chỉ có hai vận động viên chạy suốt đường đua, và người chạy thứ hai cũng quay lại với người đầu tiên.
Trong trường hợp này, luồng chương trình của bạn và quá trình I / O của hệ điều hành không "xảy ra (diễn ra) cùng một lúc", và do đó có vẻ kỳ lạ khi nói rằng các quy trình này được "đồng bộ hóa". Nhưng đó là cách nhìn sai lầm! Điều đó giống như nói: "Các vận động viên trong nhóm chuyển tiếp không chạy cùng một lúc, vì vậy họ không được đồng bộ hóa." Trong thực tế, cả hai tuyên bố đều sai! Các vận động viên trong một nhóm tiếp sức làm và phải chạy cùng một lúc, nhưng chỉ tại một thời điểm rất cụ thể: việc tắt dùi cui. Trên thực tế, chỉ có khoảnh khắc đặc biệt này trong cuộc đua mới thuyết phục chúng tôi rằng các đội tiếp sức được đồng bộ hóa để bắt đầu! Nếu chúng tôi xem yêu cầu và phản hồi I / O là "dùi cui",
Mặt khác, nếu chúng ta nghĩ về một cái gì đó như Phân tích phần tử hữu hạn trên siêu máy tính, chúng ta thấy rằng hàng ngàn quy trình phải hoạt động theo từng bước để cập nhật trạng thái toàn cầu lớn. Ngay cả khi một số nút hoàn thành công việc của họ trong một bước thời gian nhất định trước các nút khác, tất cả chúng đều cần đợi bước thời gian hoàn thành vì kết quả lan truyền đến hàng xóm qua không gian. Kiểu đồng bộ này giống như những con đom đóm: tất cả các diễn viên đều thực hiện cùng một loại nhiệm vụ.
Quy trình đa dạng
Vì lý do này, chúng tôi có thể phát minh ra một số thuật ngữ để giúp chúng tôi thấy rằng có ba loại điều đang diễn ra: "đồng bộ đồng nhất", "đồng bộ không đồng nhất" và "đồng bộ tuần tự". Vì vậy, khi các diễn viên đang thực hiện cùng một nhiệm vụ đồng thời (FEA, đom đóm), họ "đồng nhất". Khi họ đang thực hiện các nhiệm vụ khác nhau cùng một lúc (những người lính chạy so với bò so với bơi đến đích của họ, vật lý so với âm thanh so với chủ đề AI trong một trò chơi), họ "không đồng nhất". Khi họ đang thực hiện từng nhiệm vụ một, chúng là "tuần tự" (người chạy tiếp sức, chặn I / O). Chúng có thể trông rất khác nhau, nhưng chúng có chung một thuộc tính thiết yếu: tất cả các loại diễn viên thực hiện một số chờ đợi để đảm bảo rằng tất cả mọi người đến điểm đồng bộ hóa cùng một lúc. ở giữa các điểm đồng bộ hóa, hoặc "thực hiện cùng một hành động" không liên quan đến tính đồng bộ.
Các đường ống kết xuất trong GPU là đồng bộ vì tất cả chúng phải hoàn thành khung cùng nhau và bắt đầu một khung mới cùng nhau. Họ đồng nhất bởi vì họ đang làm cùng một loại công việc, và tất cả họ đều hoạt động cùng nhau. Nhưng vòng lặp trò chơi chính của máy chủ và các luồng I / O chặn xử lý đầu vào từ xa không đồng nhất vì chúng thực hiện các loại công việc rất khác nhau và một số luồng I / O sẽ không làm gì cả, vì không phải tất cả các kết nối được sử dụng. Mặc dù vậy, chúng được đồng bộ hóa, bởi vì chúng phải chia sẻ trạng thái nguyên tử (người chơi không được xem cập nhật thế giới trò chơi một phần, và máy chủ cũng không chỉ thấy một đoạn đầu vào của người chơi).
Không đồng bộ
Bây giờ, chúng ta hãy xem xét một "đọc I / O không đồng bộ". Khi chương trình của bạn gửi yêu cầu đến HĐH để đọc một chút dữ liệu từ bộ lưu trữ, cuộc gọi sẽ trả về ngay lập tức . Hãy bỏ qua các cuộc gọi lại và tập trung vào bỏ phiếu. Nói chung, thời điểm dữ liệu có sẵn cho chương trình của bạn không tương ứng với bất kỳ thời điểm đặc biệt nào liên quan đến chủ đề chương trình của bạn. Nếu chương trình của bạn không chờ đợi dữ liệu một cách rõ ràng, thì luồng sẽ không biết chính xác thời điểm đó xảy ra. Nó sẽ chỉ phát hiện ra rằng dữ liệu đang chờ trong lần kiểm tra tiếp theo.
Không có thời gian họp đặc biệt khi HĐH và luồng chương trình đồng ý bàn giao dữ liệu. Họ giống như hai con tàu đi qua trong đêm. Không đồng bộ được đặc trưng bởi sự vắng mặt của sự chờ đợi này. Tất nhiên, chuỗi chương trình thường sẽ kết thúc chờ đợi trên hoạt động I / O, nhưng nó không cần. Nó có thể vui vẻ tiếp tục thực hiện các tính toán khác trong khi quá trình tìm nạp I / O đang diễn ra và chỉ kiểm tra sau khi có thời gian rảnh. Tất nhiên, một khi HĐH đã tải xong dữ liệu, nó cũng không phải chờ đợi. Nó chỉ đặt dữ liệu ở đâu đó thuận tiện và tiếp tục công việc của mình. Trong trường hợp này, nó giống như chương trình trao dùi cui cho HĐH và HĐH xuất hiện sau đó, thả dùi cui xuống đất cùng với dữ liệu và rời khỏi đường đua. Chương trình có thể hoặc không thể chờ đợi để nhận được thông báo.
Song song
Khi chúng tôi đánh dấu một chức năng là "không đồng bộ" trong phần mềm, điều đó thường có nghĩa là chúng tôi muốn song song . Nhưng hãy nhớ rằng song song không ngụ ý đồng bộ . Những con đom đóm là một ví dụ tốt, bởi vì chúng, cũng thể hiện cả hành vi đồng bộ và không đồng bộ. Trong khi hầu hết những con ruồi đồng loạt lóe lên, nhiều con rõ ràng đã không đồng điệu với phần còn lại của nhóm và lóe lên một cách ngẫu nhiên hơn. Những con ruồi có thể đã hành động đồng thời , nhưng chúng không được đồng bộ hóa .
Bây giờ khi chúng tôi đánh dấu một số mã là "async", nó trông buồn cười, bởi vì nó ngụ ý rằng phần còn lại của mã không được đánh dấu là "đồng bộ hóa". Điều đó có nghĩa là gì? Không phải chúng tôi đã nhấn mạnh rằng "đồng bộ hóa" cần hai đến tango sao? Nhưng nếu chúng ta đang nói về việc thực thi mã trong một luồng thì sao? Trong trường hợp này, chúng ta cần lùi lại một bước và suy nghĩ về một chương trình như một chuỗi các trạng thái và chuyển tiếp giữa các trạng thái đó. Một tuyên bố trong một chương trình gây ra sự chuyển đổi trạng thái. Chúng ta có thể nghĩ về nó như là một "quy trình vi mô" bắt đầu và dừng lại với tuyên bố. Trên thực tế, các điểm trình tự được xác định bởi ngôn ngữ là các điểm đồng bộ hóa của các "quy trình vi mô" này. Và do đó, chúng ta có thể xem một luồng đơn,
Tính toàn vẹn của ngôn ngữ lập trình đảm bảo rằng các cập nhật trạng thái không can thiệp vào các câu lệnh và các điểm trình tự xác định các ranh giới mà trình biên dịch không được phép thực hiện tối ưu hóa có thể quan sát được. Ví dụ, thứ tự đánh giá các biểu thức trong một câu lệnh có thể không được xác định hoặc không được xác định rõ, cho phép trình biên dịch tự do tối ưu hóa câu lệnh theo nhiều cách khác nhau. Nhưng vào thời điểm câu lệnh tiếp theo bắt đầu, chương trình sẽ ở trạng thái được xác định rõ, nếu bản thân PL là âm thanh.
Đến bây giờ, rõ ràng chúng ta muốn nói gì về "async". Điều đó có nghĩa chính xác là hợp đồng đồng bộ ngụ ý trong một khối mã được miễn cho khối async. Nó được phép cập nhật trạng thái chương trình một cách độc lập, không có sự đảm bảo về an toàn thường được ngụ ý bởi mô hình tính toán tuần tự (nhất quán, đồng bộ). Tất nhiên, điều này có nghĩa là chúng ta cần phải đặc biệt quan tâm rằng chúng ta không phá hủy trạng thái chương trình một cách không nhất quán. Điều này thường có nghĩa là chúng tôi giới thiệu đồng bộ rõ ràng , hạn chế để phối hợp với khối async. Lưu ý rằng điều này có nghĩa là khối async có thể không đồng bộ và đồng bộ tại các thời điểm khác nhau! Nhưng nhắc lại rằng đồng bộ hóa chỉ đơn thuần cho thấy sự tồn tại của điểm đồng bộ hóa, chúng ta sẽ không gặp khó khăn khi chấp nhận khái niệm này.