thắc mắc Concurrency, Parallel, Asynchronous, Multithreading khác nhau như thế nào?

  • Người tạo chủ đề Người tạo chủ đề o0alvin0o
  • Ngày bắt đầu Ngày bắt đầu
Khi nói async thì chỉ cần hiểu đơn giản là nó là một cơ chế để k cần phải đợi cho task hoàn thành mới tiếp tục. Còn multithread là một trong những cách để implement cái async thôi. Ngay cả Single thread vẫn làm async đc.
single thread vẫn làm async được. Này mình không rõ có ngôn ngữ nào đang implement không bác để e nghiên cứu thêm. Nhưng theo e biết js là 1 ngôn ngữ khá nổi tiếng về single thread chạy async, nhưng khi e đọc xuống bản chất nó chỉ chạy single thread trên call stack thôi, còn ở phần web apis, nó vẫn có thread riêng để xử lý các task. Và khi xử lý xong, sẽ được đưa vào queue để chờ khi call stack (gọi là single thread) để xử lý. Vậy cuối cùng không phải nó cũng đưa về bài toán sẽ tạo 1 thread đẻ xử lý phần không cần chờ hả các bác. Cần lắm người thông não phần này ạ.
 
2, async của nodejs thì ko phải thế. node chỉ có 01 thread thôi. nó dùng 1 cái event loop ( vòng lặp) để chạy mỗi thứ 1 tý :D,

2 trường hợp:
1, nếu trong A bạn gọi await lệnh B thì nó nó ko chạy tiếp C, D đâu, nó chạy cái A khác, theo lời await. khi nào B return thì mới chạy tiếp C, D.

2, nếu bạn dùng B.promise (function log) thì sẽ chạy tiếp C, D -> a kết thúc và có 1 cái promise chờ chạy khi B xong. thì khi B trả về response thì đoạn function log mới chạy. và ta có async

vậy nếu B ko gọi IO, mà chỉ tốn CPU & RAM thì ở cả 2 case, nó treo luôn thằng A lẫn nodejs process. bạn có thể tự test rất dễ

còn khi dùng java thì giống như bạn, B chạy trong thread khác, thread do hệ điều hành xử lý nên ko thể khó bị treo
 
single thread vẫn làm async được. Này mình không rõ có ngôn ngữ nào đang implement không bác để e nghiên cứu thêm. Nhưng theo e biết js là 1 ngôn ngữ khá nổi tiếng về single thread chạy async, nhưng khi e đọc xuống bản chất nó chỉ chạy single thread trên call stack thôi, còn ở phần web apis, nó vẫn có thread riêng để xử lý các task. Và khi xử lý xong, sẽ được đưa vào queue để chờ khi call stack (gọi là single thread) để xử lý. Vậy cuối cùng không phải nó cũng đưa về bài toán sẽ tạo 1 thread đẻ xử lý phần không cần chờ hả các bác. Cần lắm người thông não phần này ạ.

đây là thư viện viết bằng c++, hoặc ngôn ngữ khác nhanh nhảu hơn. call như nào tôi ko rõ, nhưng nó như kiểu 1 process khác ấy

trong nodejs ko có từ khóa new thread

thread do hệ điều hành cấp phát. node ko có new thread thì gọi là single thread. nó chỉ có 1 vòng lặp như trên tôi trình bày
 
2, async của nodejs thì ko phải thế. node chỉ có 01 thread thôi. nó dùng 1 cái event loop ( vòng lặp) để chạy mỗi thứ 1 tý :D,

2 trường hợp:
1, nếu trong A bạn gọi await lệnh B thì nó nó ko chạy tiếp C, D đâu, nó chạy cái A khác, theo lời await. khi nào B return thì mới chạy tiếp C, D.

2, nếu bạn dùng B.promise (function log) thì sẽ chạy tiếp C, D -> a kết thúc và có 1 cái promise chờ chạy khi B xong. thì khi B trả về response thì đoạn function log mới chạy. và ta có async

vậy nếu B ko gọi IO, mà chỉ tốn CPU & RAM thì ở cả 2 case, nó treo luôn thằng A lẫn nodejs process. bạn có thể tự test rất dễ

còn khi dùng java thì giống như bạn, B chạy trong thread khác, thread do hệ điều hành xử lý nên ko thể khó bị treo
E cũng có làm qua sơ sơ js cũng hiểu sơ ý a nói, ở case 1 xài wait nó phải chờ là đúng, còn ở case 2 khi xài promise chạy B, C và D không phải chờ. Vậy thằng nào sẽ xử lý thằng B vậy bác, vì nếu là single thread, thì thằng single thread này đang xử lý thằng C,D rồi, không thể xử lý thằng B. kk e hỏi ngu xíu
 
E cũng có làm qua sơ sơ js cũng hiểu sơ ý a nói, ở case 1 xài wait nó phải chờ là đúng, còn ở case 2 khi xài promise chạy B, C và D không phải chờ. Vậy thằng nào sẽ xử lý thằng B vậy bác, vì nếu là single thread, thì thằng single thread này đang xử lý thằng C,D rồi, không thể xử lý thằng B. kk e hỏi ngu xíu
vẫn thằng A, nhưng thêm cái đuôi promise đấy fen, nó tạo 1 cái function, nhét vào 1 cái queue nào đấy (tôi hiểu vậy), khi B trả về response thì khi cái eventloop nó chạy qua thì sẽ gọi function

tôi làm mãi cũng hiểu đến vậy thôi.

single thread ở đây là nó chơi trick, nó là 1 cái vòng for để chạy cái đống function, mà trong đó có rất nhiều promise hoặc await :D

rất phù hợp với web api vì rất dễ hiểu khi trong code có await / promise và rất nhiều http request để trigger A
 
Em là dân trái ngành hiện đang làm Java Backend đuợc hơn nửa năm. Truớc khi học Java thì em có học C truớc (tự học), hiện tại đang có hứng thú với Rust chủ yếu viết những tool CLI linh tinh để phục vụ công việc chính. Cách đây không lâu thì có task liên quan tới async, thread, và cả OS. Khi tự tìm hiểu thì em thấy khó khăn vì không có foundation từ truờng lớp bài bản. Đây là một trò chơi hay nhưng cực kỳ risk nếu không hiểu rõ mình làm gì nên để hòan thành task em đã chọn phuơng án an toàn, đánh đổi performance và efficiency. Em nhờ các bác đi truớc giới thiệu cho em đầu sách để em tự nghiền ngẫm ạ. Em thích textbook hơn là xem nhưng nếu course chất luợng ở dạng video thì cũng không vấn đề gì.
Hiện tại em đang hiểu như sau:
  • Concurrency không nhất thiết phải dựa trên multithread vì chẳng hạn như call http request thì mình delegate task cho Socket IO, trong khi chờ response thì sẽ thực hiện những block code khác không depend vào result của socket task, tuơng tự với những device khác như Disk IO... và phần lớn việc implement đuợc compiler đảm nhiệm, dev chỉ cần declare what to do in asynchronous(C# chẳng hạn).
  • Parallel là những task thực sự đuợc execute cùng lúc và mỗi task có 1 thread riêng. Đến đây thì em lại có một thắc mắc khác là thread trong programming language mình sử dụng (với Java là JVM sẽ đảm nhiệm việc quản lý thread) có vẻ như không liên quan tới thread của OS, và thậm chí ở tầng hardware(cpu core, cpu thread) lại đuợc che đi sự phức tạp bằng 1 lớp abstraction nữa. Em cần lời khuyên là em nên tìm hiểu tới đâu, em sử dụng Java chủ yếu viết service phục vụ Enterprise là chính chả bao giờ đụng đến những cái này, Rust thì không biết tuơng lai sẽ như thế nào về nhu cầu việc làm.
  • Nếu 2 khái niệm trên em hiểu đúng, thì liệu synchronus có thể hiểu đơn giản là code run line by line, còn async thì code có thể run không theo thứ tự mình viết, lúc này lại dẫn đến một khái niệm khác cũng tuơng tự như thế là Reactive và Event driven-programming.
Đến đây thì em thực sự overload và confused nên rất cần sự giúp đỡ của các bác đi truớc. Em cảm ơn ạ
Thực ra đoạn này e hiểu khá đơn giản. Đầu tiên là bác cần phân biệt giữa process và thread:
  • Process được hệ điều hành quản lý và cấp không gian riêng biệt không liên quan đến các process khác
  • Thread cứ tính gọi là đơn vị thực thi của các process, tức là một process có thể bao gồm 1 hoặc nhiều thread.

Tiếp đến là Concurrency, Parallel. Hai cái này nói về tính chất xử lý của các job
  • Concurrency: Các job đang được xử lý xen kẽ, bác cứ tưởng tượng giờ CPU có 1 core thì sẽ trao đổi qua lại các job với nhau ( context-switching). Tập trung vào việc tối ưu rất nhiều job với ít resource
  • Parallel : Các tác vụ không phải xen kẽ mà thực hiện song song với nhau có thể là các core CPU song song với nhau. Đại loại như bọn AI xử lý dữ nhiều thì nhiều Core sẽ đọc các mảnh dữ liệu nhỏ khác nhau chứ k phải là 1 core đọc lần lượt. Tập trung vào xử lý nhiều job trên nhiều resource

Tiếp theo là Sync, Async. Hai cái này nói về phương pháp xử lý của các job
  • Sync : Xử lý tuần tự
  • Async : Bắn tứ lung tung, chạy step 1 không cần step1 phải trả về thì vẫn đi làm được việc khác, bao giờ callback của cái 1 trả về thì get kết quả (non-blocking) . Cái này giúp tối ưu hơn về I/O nhưng dễ gây ra race condition

Cuối là multithreading thì tên gọi nó cũng nói lên nó là gì rồi nên không cần giải thích thêm.
 
vẫn thằng A, nhưng thêm cái đuôi promise đấy fen, nó tạo 1 cái function, nhét vào 1 cái queue nào đấy (tôi hiểu vậy), khi B trả về response thì khi cái eventloop nó chạy qua thì sẽ gọi function

tôi làm mãi cũng hiểu đến vậy thôi.

single thread ở đây là nó chơi trick, nó là 1 cái vòng for để chạy cái đống function, mà trong đó có rất nhiều promise hoặc await :D

rất phù hợp với web api vì rất dễ hiểu khi trong code có await / promise và rất nhiều http request để trigger A
Theo e hiểu NodeJS sẽ sử dụng nhiều thread, JS code thì sẽ được execute ở main thread, còn những thứ async như Promises, etc thì sẽ được một số thread khác xử lý. Ví dụ: NodeJS xài libuv để handle network thì thư viện này sẽ có spawn (4 threads???) khác ngoài main thread.
Những threads này sẽ nằm chung trong 1 process mà OS tạo ra cho cái app NodeJS đang chạy, tùy theo số lượng core đang có mà OS sẽ quyết định threads nào sẽ được dùng để thực thi.
ví dụ máy có 1 core thì 1 core này sẽ xử lý ở main thread, sau đó nó sẽ nhảy qua xử lý ở thread của libuv, xong xuôi hết mới nhảy qua main thread xử lý tiếp (concurrently). Còn nếu máy có nhiều core hơn thì OS có thể xử lý nhiều threads song song với nhau (Parallel).
 
Theo e hiểu NodeJS sẽ sử dụng nhiều thread, JS code thì sẽ được execute ở main thread, còn những thứ async như Promises, etc thì sẽ được một số thread khác xử lý. Ví dụ: NodeJS xài libuv để handle network thì thư viện này sẽ có spawn (4 threads???) khác ngoài main thread.
Những threads này sẽ nằm chung trong 1 process mà OS tạo ra cho cái app NodeJS đang chạy, tùy theo số lượng core đang có mà OS sẽ quyết định threads nào sẽ được dùng để thực thi.
ví dụ máy có 1 core thì 1 core này sẽ xử lý ở main thread, sau đó nó sẽ nhảy qua xử lý ở thread của libuv, xong xuôi hết mới nhảy qua main thread xử lý tiếp (concurrently). Còn nếu máy có nhiều core hơn thì OS có thể xử lý nhiều threads song song với nhau (Parallel).

vẫn 1 thread. nó cache cái kết quả của promises và gọi hàm callback sau thôi, vẫn thằng main thread làm, vòng for thôi fen :D

tôi ko rõ libuv thì sao, vừa hỏi thằng copilot :D, thì nó trả lời như bạn

process / thread là khái niệm của hệ điều hành, process phải xin phép start stop, lúc nào OS nó cho mới có (ý tôi là delay của thread phụ thuộc OS, ko phụ thuộc ý chí của process)
 
single thread vẫn làm async được. Này mình không rõ có ngôn ngữ nào đang implement không bác để e nghiên cứu thêm. Nhưng theo e biết js là 1 ngôn ngữ khá nổi tiếng về single thread chạy async, nhưng khi e đọc xuống bản chất nó chỉ chạy single thread trên call stack thôi, còn ở phần web apis, nó vẫn có thread riêng để xử lý các task. Và khi xử lý xong, sẽ được đưa vào queue để chờ khi call stack (gọi là single thread) để xử lý. Vậy cuối cùng không phải nó cũng đưa về bài toán sẽ tạo 1 thread đẻ xử lý phần không cần chờ hả các bác. Cần lắm người thông não phần này ạ.
như nodejs thì ngoại trừ 4 tác vụ đặc thù cần sử dụng threadpool của libuv thì các async IO task được thực hiện bởi file descriptor dùng syscall như epoll, ko xài thêm thread
 
Chủ đề này hay đấy, đừng để mấy ông phá hoại vào. Để mình tham gia ý kiến coi như vỗ tay ủng hộ anh em.

Concurrency là thực hiện nhiều công việc cùng 1 lúc mà không quy định về "người thực thi", tức là concurrency đại diện cho cách thức xử lý công việc, vì bản chất nó là cách thức lập lịch - scheduling. Async là một trong các phương pháp thực hiện điều đó, nó có lợi cho 1 số trường hợp. Nguyên tắc tối ưu của async là làm việc gì đó khác có ích khi phải chờ đợi.
Parallel là thực hiện (nhiều) công việc trên nhiều "người thực thi" cùng lúc, như vậy nó phụ thuộc vào khái niệm "công việc" và "người thực thi", tùy cấp độ mà khái niệm này có thể khác nhau.

Trước khi thảo luận cũng nên làm rõ ngữ cảnh để tránh mất thời gian đôi co vô bổ, kiểu như multithreading là có parallel hay không, async là có mutithreading không, multithreading là có async không, có parallel không. Giới hạn ngữ cảnh xong thì trả lời mấy câu đó rất dễ.

Ví dụ khi ngữ cảnh là có thể lập trình, thì đơn vị "người thực thi" sâu đến con chip vật lý, scheduler là hệ điều hành, thì có thể lý luận nếu chỉ có 1 cpu core thì có tạo process hay thread đến giời thì vẫn không phải parallel, mà là tuần tự theo 1 cách schedule nào đó thôi (mà ngay cả khái niệm cpu core cũng bị ảnh hưởng bởi thứ mà intel gọi là hyperthreading).

Mấy cái này liên quan đến các môn ở đại học, nên đọc sách cẩn thận hơn fence rồng gì đó ở mấy trang trước. Ví dụ thực thi 1 instruction trong chip thì chỉ là tín hiệu điện chứ không cần OS làm gì.

Phân biệt bọn nó xong rồi mới xét đến được là nó có lợi hay không trong một số trường hợp cụ thể.
 
Vì chi phí context-switch của thread là rất lớn (so với một vòng lặp đơn giản). Với multithread thì sau khi yêu cầu thực hiện thao tác I/O thì có những việc sau cần phải thực hiện:
  • Backup hết tất cả các thanh ghi vào RAM, VD x86 thì bao gồm 16 thanh ghi integer, 16 thanh ghi SIMD, các thanh ghi floating point, các thanh ghi hệ thống mà user không tác động được,
  • Flush CPU cache (cache level nào thì tùy vào OS và kiến trúc),
  • Chuyển trạng thái của thread sang WAITING
  • OS scheduler kiếm một thread ready khác để thực thi (nếu có).

Đến khi I/O thực hiện xong, tức là device (VD disk, NIC) đã interrupt cho OS thì OS đổi thread đó sang trạng thái READY, nhưng điều đó không có nghĩa là nó sẽ được tiếp tục run mà còn phải chờ thread khác nữa. Khi có slot thì làm ngược lại những điều trên.

So với việc async bằng event-loop trên 1 thread thì:
  • Chỉ phải backup những thanh ghi mà coroutine đang dùng,
  • Không cần flush cache,
  • Để event-loop xác định xem coroutine nào chạy tiếp theo thì đơn giản hơn là OS scheduler xác định thread nào chạy tiếp.
đọc mãi tới page 3 mới có fen trl chuẩn, mấy fen kia viết tùm lum làm mình self doubt kiến thức vkl

ai muốn hiểu sâu về OS thì đọc cuốn operating system: three easy pieces nhé, văn phong tương đối dễ hiểu
 
Sửa lần cuối:
tiện thread này mình share luôn đợt mình optimize dự án low latency của team:
- tốc độ RAM quá thua CPU, nên hãy ưu tiên giữ trong L1/2/3 cache càng lâu càng tốt, và tránh CPU phải chờ stall, tránh false sharing
-Zero allocation branch prediction,CRTP curiously recurring template pattern
trên CPU thì có CPU Affinity, busy wait và kernel bypass
- single producer single consumer, lock free . Tránh Mutex hoặc lock
 
tiện thread này mình share luôn đợt mình optimize dự án low latency của team:
- tốc độ RAM quá thua CPU, nên hãy ưu tiên giữ trong L1/2/3 cache càng lâu càng tốt, và tránh CPU phải chờ stall, tránh false sharing
-Zero allocation branch prediction,CRTP curiously recurring template pattern
trên CPU thì có CPU Affinity, busy wait và kernel bypass
- single producer single consumer, lock free . Tránh Mutex hoặc lock
chia sẻ luôn use case, requirement, input, output thế nào đi bác
T8uPH2H.gif
 
tiện thread này mình share luôn đợt mình optimize dự án low latency của team:
- tốc độ RAM quá thua CPU, nên hãy ưu tiên giữ trong L1/2/3 cache càng lâu càng tốt, và tránh CPU phải chờ stall, tránh false sharing
-Zero allocation branch prediction,CRTP curiously recurring template pattern
trên CPU thì có CPU Affinity, busy wait và kernel bypass
- single producer single consumer, lock free . Tránh Mutex hoặc lock
cái cuối fen dùng lmax queue ah
 

Thống kê chủ đề

Ngày tạo
o0alvin0o,
Người trả lời cuối
tuong_tuong_1,
Trả lời
163
Lượt xem
29.713
Quay lại
Lên đầu trang