使用带锁的条件实例
Using a condition instance with a lock
当条件与这样的锁关联时会发生什么:
Lock lock = new ReentrantLock();
Condition notFull = lock.newCondition();
一个例子是有界缓冲区 class 例如 here
因此,例如,当调用方法 notFull.await() 和 notFull.signal() 时,正在等待 released/what 的内容将作为信号通知其他线程现在可以免费使用了。
我的假设是,在这种情况下,这些方法是 checking/signaling 锁的状态,无论是锁定还是解锁。
因此,例如,如果 lock.lock() 刚刚被调用,然后 notFull.await() 被调用,这将导致调用 notFull.await() 方法的线程成为 blocked/sent等待队列。
我的结论正确吗?
The lock associated with this Condition
is atomically released and the
current thread becomes disabled for thread scheduling purposes and
lies dormant until one of four things happens:
- Some other thread invokes the signal method for this
Condition
and the current thread happens to be chosen as the thread to be awakened;
or
- Some other thread invokes the
signalAll
method for this Condition
; or
- Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
- A "spurious wakeup" occurs.
所以需要调用
notFull.signal();
或
notFull.signalAll();
或中断正在等待的线程,否则需要进行虚假唤醒才能使正在等待的线程再次运行。
您的示例看起来像是有界阻塞队列(或其他有界阻塞池类 class)实现的一部分。通过添加项目将队列状态从非空更改为空的生产者将调用 notEmpty.notify()
,以便在 notEmpty.await()
调用中等待的消费者可以唤醒并从队列中删除新项目排队。
同样,通过删除项目将状态从已满更改为未满的消费者将调用 notFull.notify()
来唤醒在 notFull.await()
调用中被阻止的生产者。
package com.testjava;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//=========== Task1 class prints odd =====
class TaskClass1 implements Runnable
{
private Condition condition;
private Lock lock;
boolean exit = false;
int i;
TaskClass1(Condition condition,Lock lock)
{
this.condition = condition;
this.lock = lock;
}
@Override
public void run() {
try
{
lock.lock();
for(i = 1;i<11;i++)
{
if(i%2 == 0)
{
condition.signal();
condition.await();
}
if(i%2 != 0)
{
System.out.println(Thread.currentThread().getName()+" == "+i);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
lock.unlock();
}
}
}
//==== Task2 : prints even =======
class TaskClass2 implements Runnable
{
private Condition condition;
private Lock lock;
boolean exit = false;
TaskClass2(Condition condition,Lock lock)
{
this.condition = condition;
this.lock = lock;
}
@Override
public void run() {
int i;
// TODO Auto-generated method stub
try
{
lock.lock();
for(i = 2;i<11;i++)
{
if(i%2 != 0)
{
condition.signal();
condition.await();
}
if(i%2 == 0)
{
System.out.println(Thread.currentThread().getName()+" == "+i);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
lock.unlock();
}
}
}
public class OddEven {
public static void main(String[] a)
{
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Future future1;
Future future2;
ExecutorService executorService = Executors.newFixedThreadPool(2);
future1 = executorService.submit(new TaskClass1(condition,lock));
future2 = executorService.submit(new TaskClass2(condition,lock));
executorService.shutdown();
}
}
当条件与这样的锁关联时会发生什么:
Lock lock = new ReentrantLock();
Condition notFull = lock.newCondition();
一个例子是有界缓冲区 class 例如 here
因此,例如,当调用方法 notFull.await() 和 notFull.signal() 时,正在等待 released/what 的内容将作为信号通知其他线程现在可以免费使用了。
我的假设是,在这种情况下,这些方法是 checking/signaling 锁的状态,无论是锁定还是解锁。 因此,例如,如果 lock.lock() 刚刚被调用,然后 notFull.await() 被调用,这将导致调用 notFull.await() 方法的线程成为 blocked/sent等待队列。
我的结论正确吗?
The lock associated with this
Condition
is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
- Some other thread invokes the signal method for this
Condition
and the current thread happens to be chosen as the thread to be awakened; or- Some other thread invokes the
signalAll
method for thisCondition
; or- Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
- A "spurious wakeup" occurs.
所以需要调用
notFull.signal();
或
notFull.signalAll();
或中断正在等待的线程,否则需要进行虚假唤醒才能使正在等待的线程再次运行。
您的示例看起来像是有界阻塞队列(或其他有界阻塞池类 class)实现的一部分。通过添加项目将队列状态从非空更改为空的生产者将调用 notEmpty.notify()
,以便在 notEmpty.await()
调用中等待的消费者可以唤醒并从队列中删除新项目排队。
同样,通过删除项目将状态从已满更改为未满的消费者将调用 notFull.notify()
来唤醒在 notFull.await()
调用中被阻止的生产者。
package com.testjava;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//=========== Task1 class prints odd =====
class TaskClass1 implements Runnable
{
private Condition condition;
private Lock lock;
boolean exit = false;
int i;
TaskClass1(Condition condition,Lock lock)
{
this.condition = condition;
this.lock = lock;
}
@Override
public void run() {
try
{
lock.lock();
for(i = 1;i<11;i++)
{
if(i%2 == 0)
{
condition.signal();
condition.await();
}
if(i%2 != 0)
{
System.out.println(Thread.currentThread().getName()+" == "+i);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
lock.unlock();
}
}
}
//==== Task2 : prints even =======
class TaskClass2 implements Runnable
{
private Condition condition;
private Lock lock;
boolean exit = false;
TaskClass2(Condition condition,Lock lock)
{
this.condition = condition;
this.lock = lock;
}
@Override
public void run() {
int i;
// TODO Auto-generated method stub
try
{
lock.lock();
for(i = 2;i<11;i++)
{
if(i%2 != 0)
{
condition.signal();
condition.await();
}
if(i%2 == 0)
{
System.out.println(Thread.currentThread().getName()+" == "+i);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
lock.unlock();
}
}
}
public class OddEven {
public static void main(String[] a)
{
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Future future1;
Future future2;
ExecutorService executorService = Executors.newFixedThreadPool(2);
future1 = executorService.submit(new TaskClass1(condition,lock));
future2 = executorService.submit(new TaskClass2(condition,lock));
executorService.shutdown();
}
}