7 concurrency models in seven week (phần 1)
hardcore
17
concurrency model
4
White

huydx viết ngày 14/08/2016

Bài viết nằm trong chuỗi hard-core là một group học nhóm lập ra bởi một số thành viên của ruby VN. Rule của nhóm nằm tại đây Idea là mỗi week thành viên sẽ pick ra một topic và sau 1 tuần sẽ phải có output về topic đó.
Topic tuần này của mình pick là chapter đâù tiên trong cuốn Seven Concurrency Models in Seven Weeks

Cuốn sách này nói về các model trong lập trình bất đồng bộ (khác với lập trình song song, parallel programming).

Concurrent != Parallel

Đây là 2 khái niệm liên quan, nhưng hoàn toàn khác nhau. Đã có rất nhiều bài viết về vấn đề này, bạn có thể google cụm từ "concurrent vs parallel". Theo như một câu quote nổi tiếng của rob pike, tác giả của ngôn ngữ go thì

  • Concurrency is about dealing with lots of things at once.
  • Parallelism is about doing lots of things at once.

Vấn đề nằm ở "dealing" và "doing", chúng ta có thể hiểu là concurrent là làm nhiều task cùng một lúc, nhưng chưa chắc các task đó đã diễn ra song song. Chúng ta có thể hình dung thông qua tưởng tượng việc N task được giao, phải hoàn thành trong vòng 10 phút. Bạn có thể làm N task cùng một lúc nếu bạn có N cánh tay, tuy nhiên do bạn chỉ có 2 cánh tay, thế nên bạn phải làm một cách "thông minh" bằng cách switch giữa task này qua task khác, khi bạn chán 1 task, chuyển ngay qua task khác để tăng năng suất, đó chính là concurrency.

Parallel architecture

Để hiểu về concurrency, chúng ta cũng nên tìm hiểu qua về parallel một chút. Nhiều bạn nghĩ parallel chỉ đơn thuần là threading, là multi-core? Thực ra không chỉ có thế, chúng ta có rất nhiều "level" về parallel.

Bit-level parallel

Nếu bạn muốn add 2 số 32 bit trên 8 bit architecture, bạn sẽ phải thực hiện nhiều lần phép cộng trên 8bit, rồi ghép kết quả lại thành kết quả 32 bit, tuy nhiên trên 32 bit architecture, bạn sẽ phải chỉ làm điều đó 1 lần, đó chính là bit level parallel.

Instruction parallel

Bạn có thể tìm hiểu các keyword như: pipelining, out-of-order execution hay là speculative execution. Việc giải thích kĩ các concept này đi quá khuôn khổ bài viết, tuy nhiên bạn có thể hiểu idea là CPU có nhiều technique để không chỉ đơn thuần tiến hành tuần tự các instruction.

Data parallel

Bạn có thể tìm hiểu keyword SIMD, đây cũng là một kĩ thuật của GPU để giúp có thể xử lý các dữ liệu dạng vector một cách nhanh hơn

Task level parallel

Đây chính là level mà có thể "dễ nhìn" nhất với programmer, chính là lập trình song song qua multi-cores

Trên đây chính là các level về parallel, vậy chúng ta hiểu là, là một programmer ở tầng application, chúng ta phải tận dụng task level parallel để tạo ra các chương trình concurrent chạy nhanh nhất có thể. Chúng ta sẽ đi vào mô hình concurrency đầu tiên: thread và lock

Thread and Lock

Chắc các bạn nào đã từng lập trình đều đã từng nghe đến 2 keyword này. Mô hình Thread-Lock , bạn có thể hình dung mô hình này giống như một chiếc xe côn tay, mặc dù rất cơ bản và low-level, hiệu năng tốt, tuy nhiên lại rất khó để điều khiển đúng cách, và chỉ cần điều khiển sai cách sẽ đem lại hiệu năng có khi còn tồi hơn cả lập trình đồng bộ (sequential programming).
Những ví dụng trong bài viết sẽ dựa trên ngôn ngữ java, tuy nhiên concept của bài viết có thể áp dụng trên bất kì ngôn ngữ nào.

Mutual Exclusion và memory model

Mutual Exclusion chính là kĩ thuật sử dụng lock để chắc chắn là với một dữ liệu được chia sẻ với nhiều thread khác nhau, thì chỉ có một và chỉ một thread được access vào dữ liệu đó tại một thời điểm. Tuy nhiên việc sử dụng kĩ thuật lock không đúng cách có thể dẫn đến 2 tình huống rất tồi tệ có thể xẩy ra, đó là : race conditiondeadlocks.

Để "thử" về race condtion, chúng ta hãy xem một ví dụ dưới đây:

public class Puzzle {
    static boolean answerReady = false; static int answer = 0;

    static Thread t1 = new Thread() {
        public void run() { 
            answer = 42; 
            answerReady = true;
        }
    }

    static Thread t2 = new Thread() { 
        public void run() {
            if (answerReady)
                System.out.println("The meaning of life is: " + answer);
            } else 
                System.out.println("I don't know the answer");
            }
        }

    public static void main(String[] args) throws InterruptedException { 
        t1.start(); t2.start();
        t1.join(); t2.join();
    }
};

Trong đầu bạn sẽ loé lên là tuỳ theo thứ tự của t1 và t2, có thể t1 chạy trước và t2 chạy trước bạn sẽ thấy việc print ra 2 đoạn text theo thứ tự không đoán trước được, tuy nhiên việc thú vị là sau khi chạy đoạn code trên một thời gian, sẽ có khả năng chương trình được in ra với kết quả là:

The meaning of life is: 0

Hãy đọc kĩ lai đoạn code và đoạn kết quả, bạn sẽ hiểu tại sao kết quả đó sẽ là một kết quả không logic tí nào! Why? bởi vị theo như logic đoạn code thì

        answer = 42; 
        answerReady = true;

Tức là answerReady chỉ có thể true khi mà answer đã được set = 42, vậy tại sao két quả lại có thể là 0 được?? Chỉ có một lý do có thể diễn giải cho việc này, đó là do compiler đã làm gì đó với đoạn code của bạn. Bạn có thể google về jvm optimization, bạn có thể thấy vô số kết quả về việc compiler sẽ optimize một cách tự động cho đoạn code của bạn bằng cách thay đổi thứ tự của đoạn code, thậm chí còn viết lại một số đoạn code (như thay đổi vòng loop). Bạn có thể nghĩ rằng liệu việc này có cần thiết? tuy nhiên rất nhiều cải tiến về performance của các ngôn ngữ trong thời gian gần đây đến tự các optimization của compiler, thế nên việc này là không thể tránh khỏi. Vậy làm thế nào để chúng ta có thể phòng tránh các hệ quả không mong muốn như trong đoạn code trên? Chúng ta có thể phòng tránh thông qua việc nắm rõ về memory model, như được nói đến dưới đây

Memory model (memory visibility)

Java memory model sẽ định nghĩa về việc: khi nào việc thay đổi một vùng nhớ trên một thread sẽ được "nhìn thấy" bởi các thread khác cùng sử dụng vùng nhớ đó. Bạn có thể coi memory model như là "luật" mà compiler, optimizer sẽ bắt buộc phải tuân theo khi nó thay đổi đoạn code của bạn. Model này cũng nhằm mục đích chính để nối khoảng cách giữa hardware memory và software memory view khi mà 2 mô hình này hoàn toàn không giống nhau.
Cụ thể về memory model của java nằm tại link.
Một bài viết khác khá chi tiết cũng có thể tham khảo tại : http://tutorials.jenkov.com/java-concurrency/java-memory-model.html

Tạm thời đủ cho phần 1. Trong phần tiếp theo chúng ta sẽ tìm hiểu tiếp về

  • Deadlock khi sử dụng nhiều lock cùng một lúc thông qua bài toán nổi tiếng: dining philosophier (hay là bữa ăn tối của các nhà hiền triết)
  • Sử dụng các chức năng của java reentrantlock như là timeout, interrupt
  • ConcurrentLinkedList và ConcurrentHashMap sẽ giải quyết vấn đề gì?
  • CopyOnWrite Array sẽ giải quyết vấn đề gì
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

huydx

115 bài viết.
855 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
135 8
Introduction (Link) là một cuộc thi ở Nhật, và cũng chỉ có riêng ở Nhật. Đây là một cuộc thi khá đặc trưng bởi sự thú vị của cách thi của nó, những...
huydx viết hơn 1 năm trước
135 8
White
109 14
Happy programmer là gì nhỉ, chắc ai đọc xong title của bài post này cũng không hiểu ý mình định nói đến là gì :D. Đầu tiên với cá nhân mình thì hap...
huydx viết gần 3 năm trước
109 14
White
86 10
(Ảnh) Mở đầu Chắc nhiều bạn đã nghe đến khái niệm oauth. Về cơ bản thì oauth là một phương thức chứng thực, mà nhờ đó một web service hay một ap...
huydx viết hơn 2 năm trước
86 10
Bài viết liên quan
White
10 0
Hadoop là cái gì vậy? “Hadoop là một framework nguồn mở viết bằng Java cho phép phát triển các ứng dụng phân tán có cường độ dữ liệu lớn một cách ...
nguyenduyhao1111 viết hơn 1 năm trước
10 0
White
19 2
Tiếp nối phần 1 http://kipalog.com/posts/7concurrencymodelsinsevenweekphan1. Trong phần này chúng ta sẽ tiếp tục tìm hiểu về mô hình ThreadLock th...
huydx viết hơn 1 năm trước
19 2
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
115 bài viết.
855 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!