简体   繁体   English

Java中的线程:如何锁定对象?

[英]Threading in Java: How to lock an object?

The following Function is executing in its own thread: 以下函数在其自己的线程中执行:

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);
         }
}

When the execution reaches the line serverAddr.wait(60000) it throws an Exception: 当执行到达serverAddr.wait(60000)行时,它会抛出异常:

java.lang.IllegalMonitorStateException: object not locked by thread before wait()

Does anyone know how to lock an object or a function in order to prevent the concurrency? 有谁知道如何锁定对象或函数以防止并发? I've tried to add a Lock object: 我试图添加一个Lock对象:

private final Lock lock = new ReentrantLock();

and the line 和线

boolean locked = lock.tryLock();

at the beginning of function but it didn't work. 在功能的开头但它没有用。

In order to call wait() on an object, you have to hold the synchronized lock on that object (though the lock is actually released while the thread is waiting): 为了在对象上调用wait(),您必须在该对象上保持同步锁(尽管在线程等待时实际释放了锁):

synchronized (serverAddr) {
  serverAddr.wait();
}

I have to admit that why you're wanting to do this baffles me in this case... 我不得不承认,在这种情况下你为什么要这样做会让我感到困惑......

Maybe the method you are looking for is Thread.sleep(long) ? 也许你正在寻找的方法是Thread.sleep(长) This method will wait (as in stop the execution of the thread) for the specified time in milliseconds before resuming. 此方法将在恢复之前等待 (如停止执行线程)指定的时间(以毫秒为单位)。

object.wait(long) (which is what you are using) does something entirely different. object.wait(long) (这是你正在使用的)做了一些完全不同的事情。 It waits for another object from another thread to notify it (ie: send it a sort of wakeup message), and will wait at most the specified number of milliseconds. 它等待来自另一个线程的另一个对象通知它(即:发送一种唤醒消息),并且最多等待指定的毫秒数。 Given the code you posted, I highly doubt this is what you really want. 鉴于您发布的代码,我非常怀疑这是您真正想要的。

If Thread.sleep() is not what you want, then you should use the synchronized block as mentioned by the other posters. 如果Thread.sleep()不是您想要的,那么您应该使用其他海报提到的synchronized块。

I always cringe when I see this kind of code. 当我看到这种代码时,我总是畏缩。 Do yourself a favour and have a look at the java.util.concurrent package. 帮自己一个忙,看看java.util.concurrent包。

To avoid that error message, use the synchronized keyword: 要避免该错误消息,请使用synchronized关键字:

synchronized(serverAddr){
  serverAddr.wait(60000);
}

The above are correct. 以上是正确的。 You can use a synchronized block of code. 您可以使用同步的代码块。 Or you can create what they call a mutex. 或者你可以创建他们称之为互斥的东西。 A mutex can actually be any object. 互斥体实际上可以是任何对象。 Lots of people just use Object itself as a mutex. 很多人只是将Object本身用作互斥体。 Then you can lock on the mutex. 然后你可以锁定互斥锁。 Any threads wanting to get access must wait for thread holding the mutex to release it. 任何想要访问的线程都必须等待持有互斥锁的线程才能释放它。

There was also a suggestion by Apocalisp. Apocalisp也提出了一个建议。 I would also recommend that you look at the java.util.concurrent package. 我还建议您查看java.util.concurrent包。

Below code should work. 下面的代码应该工作。

     private final ReentrantLock lock = new ReentrantLock();

     lock.lock();  // block until condition holds
     try {
        serverAddr.wait(60000);
     } finally {
       lock.unlock()
     }
   }

Refer to this documentation page for more details. 有关更多详细信息,请参阅此文档页面

public void lock()

Acquires the lock. 获得锁。

Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one. 如果锁没有被另一个线程保持并获得锁定并立即返回,则将锁定保持计数设置为1。

If the current thread already holds the lock then the hold count is incremented by one and the method returns immediately. 如果当前线程已经保持锁定,则保持计数增加1并且该方法立即返回。

If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired, at which time the lock hold count is set to one 如果锁由另一个线程保持,那么当前线程将被禁用以进行线程调度,并且在获取锁定之前处于休眠状态,此时锁定保持计数设置为1

Refer to this SE question to know the advantages of lock over synchronization : 请参阅此SE问题以了解lock synchronization的优点:

Synchronization vs Lock 同步与锁定

通常,当您在Java中使用多线程程序时,您需要使用synchronized(key-word)来锁定共享变量,然后在任何时候只需一个线程就可以访问共享内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM