2012-03-30 24 views
6

Các bộ sưu tập song song có nhằm thực hiện các hoạt động có tác dụng phụ không? Nếu vậy, làm thế nào bạn có thể tránh điều kiện chủng tộc? Ví dụ:làm thế nào để tránh các điều kiện chủng tộc với bộ sưu tập song song scala

var sum=0 
(1 to 10000).foreach(n=>sum+=n); println(sum) 

50005000 

không có vấn đề với điều này. Nhưng nếu cố gắng song song, điều kiện chủng tộc xảy ra:

var sum=0 
(1 to 10000).par.foreach(n=>sum+=n);println(sum) 

49980037 
+0

Không, tác dụng phụ xấu. Nếu bạn không có nhà nước, sẽ khó khăn hơn để có điều kiện chủng tộc. – PlexQ

Trả lời

17

Trả lời nhanh: đừng làm vậy. Mã song song phải là song song, không đồng thời.

câu trả lời tốt hơn:

val sum = (1 to 10000).par.reduce(_+_) // depends on commutativity and associativity 

Xem thêm aggregate.

4

trường hợp song song không làm việc vì bạn không sử dụng các biến không ổn định do đó không đảm bảo tầm nhìn của viết của bạn và vì bạn có nhiều chủ đề mà làm như sau:

  1. đọc sum vào một thanh ghi
  2. thêm vào sổ đăng ký với giá trị sum
  3. viết giá trị được cập nhật trở lại vào bộ nhớ

Nếu 2 đề thực hiện bước 1 o đầu tiên ne sau khi khác và sau đó tiến hành để làm phần còn lại của các bước trên theo thứ tự nào, họ sẽ kết thúc ghi đè lên một trong những bản cập nhật.

  1. Sử dụng chú thích @volatile chú thích để đảm bảo khả năng hiển thị của sum khi làm điều gì đó như thế này. Xem here.
  2. Ngay cả với @volatile, do không có tính nguyên tử của số gia tăng, bạn sẽ mất một số gia số. Bạn nên sử dụng AtomicInteger s và incrementAndGet của chúng.
  3. Mặc dù sử dụng bộ đếm nguyên tử sẽ đảm bảo tính chính xác, nhưng các biến được chia sẻ ở đây cản trở hiệu suất rất lớn - biến chia sẻ của bạn giờ đây là một nút cổ chai hiệu suất vì mỗi chuỗi sẽ cố gắng ghi nguyên tử vào cùng một dòng bộ nhớ cache. Nếu bạn đã viết cho biến này không thường xuyên, nó sẽ không là vấn đề, nhưng vì bạn làm điều đó trong mỗi lần lặp lại, sẽ không có sự tăng tốc ở đây - trên thực tế, do chuyển quyền sở hữu bộ nhớ cache giữa các bộ xử lý, nó có thể sẽ chậm hơn .

Vì vậy, như Daniel đã đề xuất - hãy sử dụng reduce cho việc này.

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