[英]Threading in Java: How to lock an object?
以下函數在其自己的線程中執行:
private void doSendData()
{
try {
//writeToFile(); // just a temporary location of a call
InetAddress serverAddr = InetAddress.getByName(serverAddress);
serverAddr.wait(60000);
//Log.d("TCP", "C: Connecting...");
Socket socket = new Socket(serverAddr, portNumber);
socket.setSoTimeout(3000);
try {
//Log.d("TCP", "C: Sending: '" + message + "'");
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
String message = packData();
out.println(message);
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
connectionAvailable = true;
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
connectionAvailable = false;
} finally {
socket.close();
announceNetworkAvailability(connectionAvailable);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
announceNetworkAvailability(connectionAvailable);
}
}
當執行到達serverAddr.wait(60000)
行時,它會拋出異常:
java.lang.IllegalMonitorStateException: object not locked by thread before wait()
有誰知道如何鎖定對象或函數以防止並發? 我試圖添加一個Lock對象:
private final Lock lock = new ReentrantLock();
和線
boolean locked = lock.tryLock();
在功能的開頭但它沒有用。
為了在對象上調用wait(),您必須在該對象上保持同步鎖(盡管在線程等待時實際釋放了鎖):
synchronized (serverAddr) {
serverAddr.wait();
}
我不得不承認,在這種情況下你為什么要這樣做會讓我感到困惑......
也許你正在尋找的方法是Thread.sleep(長) ? 此方法將在恢復之前等待 (如停止執行線程)指定的時間(以毫秒為單位)。
object.wait(long) (這是你正在使用的)做了一些完全不同的事情。 它等待來自另一個線程的另一個對象通知它(即:發送一種喚醒消息),並且最多等待指定的毫秒數。 鑒於您發布的代碼,我非常懷疑這是您真正想要的。
如果Thread.sleep()不是您想要的,那么您應該使用其他海報提到的synchronized塊。
當我看到這種代碼時,我總是畏縮。 幫自己一個忙,看看java.util.concurrent
包。
要避免該錯誤消息,請使用synchronized關鍵字:
synchronized(serverAddr){
serverAddr.wait(60000);
}
以上是正確的。 您可以使用同步的代碼塊。 或者你可以創建他們稱之為互斥的東西。 互斥體實際上可以是任何對象。 很多人只是將Object本身用作互斥體。 然后你可以鎖定互斥鎖。 任何想要訪問的線程都必須等待持有互斥鎖的線程才能釋放它。
Apocalisp也提出了一個建議。 我還建議您查看java.util.concurrent包。
下面的代碼應該工作。
private final ReentrantLock lock = new ReentrantLock();
lock.lock(); // block until condition holds
try {
serverAddr.wait(60000);
} finally {
lock.unlock()
}
}
有關更多詳細信息,請參閱此文檔頁面 。
public void lock()
獲得鎖。
如果鎖沒有被另一個線程保持並獲得鎖定並立即返回,則將鎖定保持計數設置為1。
如果當前線程已經保持鎖定,則保持計數增加1並且該方法立即返回。
如果鎖由另一個線程保持,那么當前線程將被禁用以進行線程調度,並且在獲取鎖定之前處於休眠狀態,此時鎖定保持計數設置為1
請參閱此SE問題以了解lock
synchronization
的優點:
通常,當您在Java中使用多線程程序時,您需要使用synchronized(key-word)來鎖定共享變量,然后在任何時候只需一個線程就可以訪問共享內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.