什么是java中的条件变量? [英] What is a Condition Variable in java?

查看:267
本文介绍了什么是java中的条件变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Q1。 Java中的一个condVar是什么?如果我看到下面的代码,条件变量必须在 mutex.acquire()'和' mutex.release()'块内



  public void put(Object x)throws InterruptedException {
mutex.acquire();
尝试{
while(count == array.length)
notFull.await();
数组[putPtr] = x;
putPtr =(putPtr + 1)%array.length;
++ count;
notEmpty.signal();
}
finally {
mutex.release();
}
}

我有三个线程 myThreadA myThreadB myThreadC 运行,它调用相同的函数 commonActivity(),这将触发函数 myWorkReport()

  public void myWorkReport(){
mutexMyWork.acquire();
try {
while(runMyWork){
doWork();
conditionMyWork.timedwait(sleepMyWork);
}
}
finally {
mutexMyWork.release()
}
}

public void commonActivity(){
try {
conditionMyWork.signal();
} finally {
// cleanup
}
}

public void myThreadA(){
mutexA.acquire();
try {
while(runningA){// runningA是一个布尔变量,只要应用程序正在运行
conditionA.timedwait(sleepA),它始终为true;
commonActivity();
}
}
finally {
mutexA.release();
}
}


public void myThreadB(){
mutexB.acquire();
尝试{
while(runningB){// runningB是一个布尔变量,只要应用程序运行
conditionB.timedwait(sleepB),它始终为true;
commonActivity();
}
}
finally {
mutexB.release();
}
}

public void myThreadC(){
mutexC.acquire();
尝试{
while(runC){// runningC是一个布尔变量,只要应用程序正在运行,它始终为true。
conditionC.timedwait(sleepC);
commonActivity();
}
}
finally {
mutexC.release();
}
}

Q2。正在使用timedwait一个好的做法。我可以通过使用sleep()实现相同。如果使用sleep()调用不好,为什么?



Q3。有没有更好的方法来做上述的事情?

Q4。对于每个 condition.timedwait(time); ,必须具有 condition.signal() / strong>

解决方案

Q1)最好的资源可能是 JavaDoc 。条件变量是允许您在允许您的方法继续之前测试特定条件成立的机制。在您的示例中,有两个条件, notFull notEmpty



您的示例中显示的put方法在尝试添加元素之前等待 notFull 条件成为true进入数组,一旦插入完成,它就会发出 notEmpty 条件,以唤醒阻止等待从数组中删除元素的任何线程。


...一个条件变量必须
必须在
'mutex.acquire()'和
'mutex之内。 release()'block?


任何调用条件变量的调用都需要在同步区域内 - 这可以通过内置 synchronized 关键字或由 java.util.concurrent 包提供的同步器类之一,例如锁定。如果您没有同步条件变量,有两个可能的负面结果:


  1. 错过的信号 - 这是一个线程检查一个条件,并发现它不成立,但在阻止另一个线程进来之前,执行一些操作以使条件变为true,然后发送所有等待条件的线程。不幸的是,第一个线程已经检查了条件,并且即使实际可以进行阻止。


  2. 第二个问题是通常的问题,你可以有多个线程尝试同时修改共享状态。在您的示例的情况下,多个线程可以同时调用 put(),然后它们都会检查该条件,并看到数组未满,并尝试插入到该对象中,从而覆盖数组中的元素。


Q2)定时等待对调试有用目的是允许您在线程未通过信号唤醒的情况下记录信息。



使用 sleep()代替定时等待不是一个好主意,因为如上所述,您需要在同步区域内调用 await()方法,而 sleep()不释放任何持有的锁,而 await()。这意味着任何睡眠线程仍然会保持他们已经获得的锁,导致其他线程不必要地阻塞。



Q4)如果您使用了定时等待,则不需要调用 signal(),但是这样做意味着所有等待都将不会返回,直到超时过去,这是至少无效的。


Q1. What is a condVar in Java? If I see the code below, does a condition variable necessarily have to be within the 'mutex.acquire()' and 'mutex.release()' block?

public void put(Object x) throws InterruptedException {
   mutex.acquire();
   try {
      while (count == array.length)
      notFull.await();
      array[putPtr] = x;
      putPtr = (putPtr + 1) % array.length;
      ++count;
      notEmpty.signal();
  }
  finally {
     mutex.release();
  }
}

I have three threads myThreadA, myThreadB, myThreadC running which call the same function commonActivity() which triggers the function myWorkReport() e.g.

public void myWorkReport(){
    mutexMyWork.acquire();
    try{
         while(runMyWork){
             doWork();
             conditionMyWork.timedwait(sleepMyWork);
         }
    }
    finally{
       mutexMyWork.release()
    }    
}

public void commonActivity(){
    try{
        conditionMyWork.signal(); 
    }finally{
        //cleanup
    }   
}

public void myThreadA(){
    mutexA.acquire();
    try{
        while(runningA){    //runningA is a boolean variable, this is always true as long as application is running
            conditionA.timedwait(sleepA);
            commonActivity();
        }
    }
    finally{
        mutexA.release();
    }
}


public void myThreadB(){
    mutexB.acquire();
    try{
        while(runningB){    //runningB is a boolean variable, this is always true as long as application is running
            conditionB.timedwait(sleepB);
            commonActivity();
        }
    }
    finally{
        mutexB.release();
    }
}

public void myThreadC(){
    mutexC.acquire();
    try{
        while(runningC){    //runningC is a boolean variable, this is always true as long as application is running.
            conditionC.timedwait(sleepC);
            commonActivity();
        }
    }
    finally{
        mutexC.release();
    }
}

Q2. Is using timedwait a good practice. I could have achieved the same by using sleep(). If using sleep() call is bad, Why?

Q3. Is there any better way to do the above stuff?

Q4. Is it mandatory to have condition.signal() for every condition.timedwait(time);

解决方案

Q1) The best resource for this is probably the JavaDoc for the Condition class. Condition variables are a mechanism that allow you to test that a particular condition holds true before allowing your method to proceed. In the case of your example there are two conditions, notFull and notEmpty.

The put method shown in your example waits for the notFull condition to become true before it attempts to add an element into the array, and once the insertion completes it signals the notEmpty condition to wake up any threads blocked waiting to remove an element from the array.

...does a condition variable necessarily have to be within the 'mutex.acquire()' and 'mutex.release()' block?

Any calls to change the condition variables do need to be within a synchronized region - this can be through the built in synchronized keyword or one of the synchronizer classes provided by the java.util.concurrent package such as Lock. If you did not synchronize the condition variables there are two possible negative outcomes:

  1. A missed signal - this is where one thread checks a condition and finds it does not hold, but before it blocks another thread comes in, performs some action to cause the condition to become true, and then signals all threads waiting on the condition. Unfortunately the first thread has already checked the condition and will block anyway even though it could actually proceed.

  2. The second issue is the usual problem where you can have multiple threads attempting to modify the shared state simultaneously. In the case of your example multiple threads may call put() simultaneously, all of them then check the condition and see that the array is not full and attempt to insert into it, thereby overwriting elements in the array.

Q2) Timed waits can be useful for debugging purposes as they allow you to log information in the event the thread is not woken up via a signal.

Using sleep() in place of a timed wait is NOT a good idea, because as mentioned above you need to call the await() method within a synchronized region, and sleep() does not release any held locks, while await() does. This means that any sleeping thread will still hold the lock(s) they have acquired, causing other threads to block unnecessarily.

Q4) Technically, no you don't need to call signal() if you're using a timed wait, however, doing so means that all waits will not return until the timeout has elapsed, which is inefficient to say the least.

这篇关于什么是java中的条件变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆