2015-09-22 13 views
5

Tôi có một phương thức gọi là processOutbox. Tôi muốn nó là chủ đề an toàn. Tôi không muốn một thread để gọi phương thức này trong khi một thread là ở đó. Tôi đã thực hiện nó theo cách sau. Tôi đã làm nó đúng chưa? Có bất kỳ sơ hở nào trong việc triển khai của tôi không? Nếu có bất kỳ, sau đó xin vui lòng tư vấn về cách tôi có thể giải quyết nó.Làm cách nào để đảm bảo an toàn luồng trong ngữ cảnh sau?

this.start(); 
    outboxLock.lock(); 
    timer = new Timer(); 
    try{ 
    timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 
       processOutbox(); 
      } 
     }, 0, period); 
    } finally{ 
     outboxLock.unlock(); 
    } 
+4

Bạn chỉ khóa lịch biểu. Việc thực hiện vẫn không an toàn. – Fildor

+0

Tôi làm như thế nào? Làm ơn cho lời khuyên. – mayooran

+0

Tôi khuyên bạn nên đồng bộ hóa nó trên biến tĩnh cấp lớp. –

Trả lời

5

Nếu bạn muốn chắc phương pháp processOutbox của bạn, bạn nên sử dụng từ khóa synchronized:

public class YourClass{ 
    public synchronized void processOutbox(){ 
     //do all you want 
    } 
} 

Thông tin thêm tại địa chỉ: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Nếu trong mã của bạn, bạn có một thể hiện của YourClass gọi ví dụ: myInstance, tất cả các cuộc gọi đến processOutbox() sẽ là chủ đề an toàn vì chúng sẽ bị khóa ở cấp độ thể hiện.

Ví dụ:

YourClass myInstance = new YourClass(); 
Thread thread1 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
Thread thread2 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
thread1.start(); 
thread2.start(); 

Đây thead2 sẽ chờ đợi cho đến khi thread1 kết thúc cuộc gọi đến "processOutbox"

Nhưng ví dụ:

YourClass myInstance = new YourClass(); 
YourClass myInstance2= new YourClass(); 
Thread thread1 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
}; 
Thread thread2 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance2.processOutbox(); 
    } 
} 
thread1.start(); 
thread2.start(); 

thead2 sẽ KHÔNG chờ đợi vì họ đang gọi phương thức trên các trường hợp khác nhau.

Một người nào đó được hỏi cụ thể về cách sử dụng ReentrantLock - Vì vậy, tôi sẽ thêm câu trả lời đó vào câu trả lời này vì điều này là chính xác.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     outboxLock.lock() 
     try { 
      // do stuff 
     } finally { 
      outboxLock.unlock() 
     } 
    } 
} 

Tôi đề cập cụ thể vì bạn cũng có thể làm mọi thứ, nơi bạn giữ các chủ đề khác ngoài khóa mà không làm cho chúng bị chặn bằng cách sử dụng tryLock thay thế.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     if(outboxLock.tryLock()) { 
      try { 
       // do stuff 
      } finally { 
       outboxLock.unlock() 
      } 
     } 
    } 
} 
+0

** Tôi không muốn một thread khác gọi phương thức này trong khi chỉ có một luồng. ** –

+0

Java API: "Khi một luồng đang thực hiện một phương thức được đồng bộ hóa cho một đối tượng, tất cả các luồng khác gọi ra các phương thức đồng bộ cho cùng một khối đối tượng (đình chỉ thực thi) cho đến khi chuỗi đầu tiên được thực hiện với đối tượng. " –

+0

Làm thế nào tôi có thể đạt được cùng một bằng cách sử dụng reentrantlock? xin vui lòng tư vấn goku :) – mayooran

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