2016-04-15 59 views
2

我有一個主線程和一個工作線程。主線程將任務添加到隊列中,並且工作線程使他們計算數據。在將對象放入隊列之前,我調用任務對象內的ReentrantLock對象(主線程上的)的鎖定。當工作線程完成處理隊列中的任務時,我會調用解鎖(工作線程上的)。問題是我得到一個IllegalMonitorStateException,因爲我在不同的線程上調用鎖定和解鎖。Java鎖和解鎖不同的線程

我正在尋找一個替代鎖定系統,我可以在不同的線程上做到這一點。

例子:

public class Worker extends Thread { 
    public static Queue<Task> tasks = new ConcurrentLinkedQueue<Task>(); 

    @Override 
    public void run() { 
     while (true) { 
      Task task = tasks.poll(); 

      if (task != null) { 
       task.work(); 
       task.lock.unlock(); // Here is the unlock, Task#i should not change up to now 
      } 
     } 
    } 
} 


public class Task { 
    private int i = 0; 
    public Lock lock; 

    public void setI(int i) { 
     lock.lock(); 
     this.i = i; 
     lock.unlock(); 
    } 

    public void work() { 
     System.out.println(i); 
    } 
} 


public class Test { 
    Task task = new Task(); 

    public void addTask() { 
     task.lock.lock(); // Here is the lock, Task#i should not change 
     Worker.tasks.add(task); 
    } 
} 
+0

你用鎖鎖住什麼? – Savior

+0

@Pillar對象內的數據。 – stonar96

+0

在鎖定和解鎖之前在對象上同步 – ControlAltDel

回答

1

爲什麼不使用Semaphore只有一個許可證?而不是鎖定操作,您獲得單一許可證。您應該始終使用release()釋放鎖。

0

按的問題,它看起來並不設計多線程應用正確的方式。

工作線程應該處理對象的創建,或者您應該將不可變對象傳遞給工作線程,一旦工作線程完成,它可以將結果傳遞迴主線程。

我不認爲在一個線程中獲取鎖定並在另一個線程中解鎖是不太可能的。

+0

我無法重新設計應用程序。我修改一個應用程序。原始應用程序是單線程的,我想添加這個工作線程,它應該在添加到隊列中時處理對象的狀態。 – stonar96

0

您不需要替代鎖定系統。數據結構ConcurrentLinkedQueue已經提供了自己的鎖定系統並保證了線程安全。任何額外的鎖定是不必要的

但是你正在重新發明這裏的車輪。我建議你看看ExecutorServiceThreadPools。雖然自己構建事物是一種很好的學習體驗。它也是錯誤的重要來源。

ExecutorService workerPool = Executors.newFixedThreadPool(10); // 10 worker threads 
... 
Runnable myTask = ...; 
workerPool.submit(myTask); // called from the main thread 
...