2013-07-24 23 views
6

Chúng tôi đang xây dựng một ứng dụng web với Scala, khung chơi và MongoDB (với ReactiveMongo làm trình điều khiển của chúng tôi). Kiến trúc ứng dụng không bị chặn để kết thúc.Sử dụng đồng bộ/khóa trong mã sau

Trong một số phần trong mã của chúng tôi, chúng tôi cần truy cập một số thư viện không an toàn theo chủ đề như bộ phối hợp phân tích cú pháp của Scala, phản xạ của Scala v.v. Chúng tôi hiện đang bao gồm các cuộc gọi như vậy trong khối synchronized. Tôi có hai câu hỏi:

  1. Có bất kỳ dấu hiệu nào cần tìm khi sử dụng synchronized với mã y trong tương lai không?
  2. Bạn nên sử dụng khóa (chẳng hạn như ReentrantLock) thay vì synchronized, từ cả quan điểm hiệu suất và khả năng sử dụng?
+0

Tôi gặp khó khăn khi hiểu ý bạn là gì "mã tương lai" – fge

+0

@fge, mã sử dụng nhiều từ 'Future's. Tôi nghĩ điều đó hoàn toàn rõ ràng từ ngữ cảnh (Play, Reactive * etc), nhưng có vẻ như không phải vậy, nên xin lỗi. – missingfaktor

+1

Bạn không nên thực hiện các thao tác chặn với ngữ cảnh thực thi mặc định. [Câu trả lời này] (http://stackoverflow.com/a/16834855/406435) có thể hữu ích. – senia

Trả lời

2

Ví dụ bạn đề cập tức là phản ánh và phân tích cú pháp không hợp lý và bạn không cần khóa, nhưng nếu bạn định sử dụng khóa thì khối đồng bộ sẽ thực hiện. Tôi không nghĩ có nhiều sự khác biệt về hiệu suất giữa việc sử dụng đồng bộ hóa với Khóa.

8

Đây là câu hỏi cũ)) xem tại đây using-actors-instead-of-synchronized chẳng hạn. Nói tóm lại nó sẽ được khuyến khích hơn để sử dụng các diễn viên thay vì khóa:

class GreetingActor extends Actor with ActorLogging { 

    def receive = { 
    case Greeting(who) ⇒ log.info("Hello " + who) 
    } 
} 

chỉ có một thông báo sẽ được xử lý tại bất kỳ thời điểm nào, vì vậy bạn có thể đặt bất kỳ không sợi đang an toàn, bạn muốn thay vì log.info, mọi thứ sẽ hoạt động OK. BTW sử dụng mẫu yêu cầu bạn có thể tích hợp liền mạch các diễn viên của mình vào mã hiện có yêu cầu tương lai.

+0

Bạn có thể vui lòng giải thích về "mô hình yêu cầu" là gì và cách sử dụng nó? – missingfaktor

+1

Tôi không thể làm tốt hơn tài liệu chính thức http: //doc.akka.io/docs/akka/snapshot/scala/actors.html # Ask__Send-And-Receive-Future – vitalii

3

Đối với tôi, vấn đề chính mà bạn sẽ gặp phải là mọi cuộc gọi đến một phần được mã hóa hoặc bị khóa có thể bị chặn và do đó làm tê liệt các luồng của ngữ cảnh thực thi. Để tránh vấn đề này, bạn có thể quấn bất kỳ cuộc gọi đến một phương pháp có khả năng ngăn chặn sử dụng scala.concurrent.blocking:

import scala.concurrent._ 
import ExecutionContext.Implicits.global 

def synchronizedMethod(s: String) = synchronized{ s.size } 

val f = future{ 
    println("Hello") 
    val i = blocking{ //Adjust the execution context behavior 
    synchronizedMethod("Hello") 
    } 
    println(i) 
    i 
} 

Tất nhiên, nó có thể tốt hơn để xem xét lựa chọn thay thế như biến thread-địa phương hoặc gói gọi mã serial bên một diễn viên.

Cuối cùng, tôi khuyên bạn nên sử dụng đồng bộ hóa thay vì khóa. Đối với hầu hết các ứng dụng (đặc biệt là nếu các phần quan trọng là rất lớn), sự khác biệt hiệu suất là không đáng chú ý.

+1

+1 cho mẹo chặn(). Đồng ý sử dụng 'đồng bộ hóa 'trừ khi bạn muốn tận dụng lợi thế của việc bỏ phiếu khóa, thời gian chờ, gián đoạn, v.v. – sourcedelica

2

Tôi nghĩ rằng cách dễ nhất và an toàn nhất sẽ là (nếu bạn có thể) từ Chú thích Chủ đề. tức là mỗi chuỗi tạo một cá thể của trình kết hợp phân tích cú pháp của riêng nó, v.v. sau đó sử dụng nó.

Và trong trường hợp bạn cần bất kỳ đồng bộ hóa nào (nên tránh dưới dạng lưu lượng truy cập, nó sẽ là kẻ giết người), synchornized hoặc ReentrantLock sẽ mang lại hiệu suất gần như giống nhau. Nó một lần nữa phụ thuộc vào những gì các đối tượng cần phải được bảo vệ trên những gì khóa vv Trong một ứng dụng web, nó được khuyến khích, trừ khi hoàn toàn cần thiết.

+0

Bạn có thể vui lòng cung cấp thêm thông tin về cách đạt được sự giam giữ chỉ định không? – missingfaktor