2013-12-12 16 views
14

Tôi đang cố gắng hiểu mô hình và chuỗi bộ nhớ Java. Như tôi đã hiểu, mỗi luồng có một bản sao cục bộ của bộ nhớ "chính". Vì vậy, nếu một chủ đề cố gắng thay đổi biến số int, ví dụ, đối với một số đối tượng, nó sẽ lưu biến biến số int và nếu thay đổi nó, luồng khác có thể không thấy thay đổi. Nhưng nếu chủ đề cache một số đối tượng thay vì int? Những gì đề cache trong trường hợp này? Nếu một luồng lưu trữ một tham chiếu đến một đối tượng, bất kỳ thay đổi nào đối với trạng thái của đối tượng không hiển thị với các luồng khác? Tại sao?Mô hình bộ nhớ đệm và mô hình bộ nhớ Java

Cảm ơn bạn trước

Trả lời

11

Chủ đề không có bản sao bộ nhớ cục bộ. Một phần của bộ nhớ mà chủ đề đọc/ghi có thể là từ bộ nhớ cache, thay vì bộ nhớ chính. Bộ đệm không cần phải đồng bộ với nhau hoặc đồng bộ với bộ nhớ chính. Đây là nơi bạn có thể quan sát mâu thuẫn.

Vì vậy, nếu một chủ đề cố gắng thay đổi biến int, ví dụ như đối tượng nào đó lưu biến int và nếu thay đổi thì chuỗi khác có thể không thấy thay đổi.

Điều đó là chính xác. Mô hình Bộ nhớ Java được xác định trong trường hợp xảy ra trước các quy tắc, ví dụ: có một xảy ra trước khi quy tắc giữa một ghi dễ bay hơi của trường x và đọc dễ bay hơi của trường x. Vì vậy, khi viết xong, đọc tiếp theo sẽ thấy giá trị được viết.

Nếu không xảy ra như vậy trước khi quan hệ, tất cả các cược sẽ bị tắt (cũng có thể sắp xếp lại hướng dẫn có thể làm cho cuộc sống trở nên phức tạp khi không xảy ra trước khi quy tắc).

Nếu chuỗi lưu trữ tham chiếu đến một đối tượng bất kỳ thay đổi trạng thái của đối tượng cũng không hiển thị với các chủ đề khác? Tại sao?

Nó có thể hiển thị .. nó cũng có thể không hiển thị. Nếu không có một điều xảy ra trước khi quy tắc, tất cả các cược là của. Lý do tại sao nếu không có rất nhiều tối ưu hóa như thủ thuật phần cứng để tăng tốc độ, hoặc thủ thuật biên dịch sẽ không được phép. Và tất nhiên, luôn giữ bộ nhớ đồng bộ với bộ nhớ cache, sẽ giảm hiệu suất.

+1

Lưu ý rằng "tiếp theo" không giống với "xảy ra sau khi viết". 'volatile' không cung cấp bất kỳ sự đảm bảo * kịp thời nào *, nó chỉ là về * tính nhất quán * trong việc không bao giờ quan sát viết ra theo thứ tự. –

+0

@pveentjer Tại sao bạn nói như - nó có thể được nhìn thấy .. nó cũng có thể không được hiển thị? Chỉ tham chiếu được lưu trong bộ đệm cục bộ luồng. Vì vậy, các thay đổi sẽ hiển thị trên các chuỗi. Liệu tôi có sai ? Thủ thuật phần cứng/trình biên dịch - Bạn có thể đưa ra một bức tranh rõ ràng hơn không. – Kiran

-3

Mỗi chủ đề không có bản sao bộ nhớ cục bộ. Nếu một biến được hiển thị (vì phạm vi của nó) đến nhiều hơn một luồng, mỗi chuỗi sẽ thấy cùng một giá trị.

Tuy nhiên, các chương trình đa luồng cần phải rất cẩn thận về việc chia sẻ các biến (bộ nhớ) vì rất dễ giới thiệu các điều kiện chủng tộc nếu bạn không cẩn thận.

+2

Tôi không nghĩ như vậy, vì lý do nào khác mà từ khóa ´volatile 'tồn tại? – Chriss

+0

Chriss và Steve, tôi nghĩ cả hai bạn không hoàn toàn đúng. Không có những thứ như bộ nhớ đệm trong bộ nhớ địa phương (tôi tin rằng có bộ đệm luồng trong các phiên bản trước của JVM). Biến động tồn tại vì nhiều lý do khác: 1. Để ngăn CPU sắp xếp lại (trong trường hợp thực hiện đa lõi và đa bộ xử lý) 2. Để ngăn chặn tối ưu hóa trình biên dịch và JIT có thể ngắt truy cập đồng thời vào các biến được chia sẻ. Và không có liên quan gì đến điều kiện chủng tộc. Dễ bay hơi có thể giúp bạn tránh chúng trong một số trường hợp, nhưng đó là một vấn đề chung chung hơn. –

2

"Trước khi bạn có thể viết phong nha mã đa luồng, tuy nhiên, bạn thực sự cần phải nghiên cứu thêm về sự phức tạp và tinh tế của đa luồng mã.

Khi nói đến chủ đề, rất ít được đảm bảo.

Bạn có thể tưởng tượng sự tàn phá có thể xảy ra khi hai luồng khác nhau truy cập vào một cá thể của một lớp, cả hai luồng đều gọi các phương thức trên đối tượng đó ... và các phương thức đó sửa đổi trạng thái của đối tượng? ... quá đáng sợ để thậm chí hình dung. ", từ Sun Certified Programmer cho Java 6, chương 9: Chủ đề.

Bạn tôi,

Trong Java, chủ đề không cache bất kỳ đối tượng hay thay đổi, họ chỉ có một tham chiếu đến mộtdụ của một đối tượng . Nói về bộ nhớ cache của chủ đề giống như nói về các luồng hệ thống tác vụ ... Java hoạt động theo cùng một cách trong tất cả hệ điều hành, cho dù chủ đề được quản lý nội bộ như thế nào, rất khác nhau tùy thuộc vào hệ điều hành khác nhau.

Nhìn một mã này:

AccountDanger r = new AccountDanger(); 
Thread one = new Thread(r): 
Thread two = new Thread(r); 

Như bạn có thể thấy, trong trường hợp này đề có quyền truy cập vào cùng một ví dụ: r. Sau đó, bạn sẽ gặp sự cố đồng bộ, chắc chắn ... không quan trọng nếu chúng tôi nói về thành viên gốc hoặc đối tượng, chủ đề một và hai sẽ có quyền truy cập vào tất cả các thành viên r (nếu chúng là có thể truy cập qua phạm vi hoặc người định cư/getters) và họ sẽ đọc trực tiếp các giá trị từ ví dụ r. Điều này là chắc chắn ngay cả khi bạn không nhận thấy nó, mà đôi khi thực sự khó khăn.

Tôi khuyên bạn nên đọc khoảng phạm vi javađồng bộ hóa java, nếu bạn muốn mã hóa các ứng dụng đa luồng.

Kính trọng,

8

CPU có nhiều bộ đệm. Đó là những bộ đệm phần cứng có thể có các bản sao dữ liệu không nhất quán. Lý do họ có thể không phù hợp là giữ mọi thứ nhất quán có thể làm chậm mã của bạn theo hệ số 10 và hủy hoại bất kỳ lợi ích nào bạn nhận được từ việc có nhiều chuỗi. Để có được hiệu suất tốt, bạn cần phải được chọn lọc phù hợp. Mô hình bộ nhớ Java mô tả khi nào nó sẽ đảm bảo dữ liệu là nhất quán, nhưng trong trường hợp đơn giản nhất thì nó không.

Lưu ý: đây không chỉ là vấn đề về CPU. Một trường không nhất quán giữa các luồng có thể được gạch chân trong mã. Điều này có thể có nghĩa là nếu một luồng thay đổi giá trị, một luồng khác có thể KHÔNG BAO GIỜ thấy sự thay đổi này vì nó đã được ghi vào mã.

17

CPU có bộ đệm mức độ khác nhau L1, L2, L3. Mỗi CPU (và/cũng có thể CPU Core) có bộ nhớ cache riêng. Bộ đệm này lưu trữ bộ nhớ chính (RAM) tối thiểu để thực hiện.

_______________ ______________ 
|  CPU 1  | |  CPU 2 | 
| _________ | | _________ | 
| | Level 1 | | | | Level 1 | | 
| | Cache | | | | Cache | | 
| |   | | | |   | | 
| |_________| | | |_________| | 
|_______________| |______________| 
      | |    | | 
      | |    | | 
      _|_|______________|_|__ 
     |      | 
     |  MAIN MEMORY  | 
     |_______________________| 


    Time  Command     CPU 1 (Cache)  CPU 2 (Cache)  Main Memory  
------- ----------    ---------------- --------------  ------------- 
    1   ---      ---    ---    x = 10 
    2  Read x (on cpu1)   x = 10    ---    x = 10 
    3  Write x <--20 (on cpu1)  x = 20    ---    x = 10  
    4  Read x (on cpu2)   x = 20    x = 10    x = 10 
    5  put cache to Main mem  x = 20    x = 10    x = 20 

Ví dụ: Thứ tự thực hiện trên, giá trị x sai trên CPU2. Giá trị x đã được thay đổi bởi CPU1. Nếu x biến được định nghĩa là dễ bay hơi, tất cả các hoạt động ghi phản ánh vào bộ nhớ chính ngay lập tức.

Các vấn đề liên quan