Я пытаюсь понять метод lockInterruptibly. До сих пор я понял: void lockInterruptibly () -> получает блокировку, если она доступна, и выполняет обычные операции. Если блокировка недоступна, то поток переходит в состояние ожидания и во время ожидания объекта блокировки, если поток прерывается, он не получит объект блокировки. Если оно не прервано, то только оно получит блокировку.
Я пытался понять из Java docs API , однако мне это не очень понятно. Может ли кто-нибудь выразить это другими словами?
Также я не могу понять, как ниже приведен возможный результат для этой программы?
Possible output 1)
Before interrupt Hello....
After t1.interrupt Hello and before t2.start()....
exception caught test1
After t2.start Hello but before t2.interrupt....
After t2.interrupt Hello....
exception caught test2
Main Hello....
Main Hello....
Main Hello....
Possible output 2)
Before interrupt Hello....
After t1.interrupt Hello and before t2.start()....
exception caught test1
After t2.start Hello but before t2.interrupt....
After t2.interrupt Hello....
Main Hello....
Main Hello....
Main Hello....
exception caught test2
Программа: -
import java.util.concurrent.locks.*;
class Test{
static Lock1 l = new Lock1();
public void test1() throws InterruptedException{
l.lockInterruptibly();
synchronized(l){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +" : " + i);
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println(Thread.currentThread().getName() + " got interrupted");
}
}
}
}
public void test2() throws InterruptedException{
l.lockInterruptibly();
synchronized(l){
for(int i=100; i>0; i--){
System.out.println(Thread.currentThread().getName() +" : " + i);
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println(Thread.currentThread().getName() + " got interrupted");
}
}
}
}
}
class MyThread1 extends Thread{
Test t;
MyThread1(String name, Test t){
super(name);
this.t = t;
}
public void run(){
try{
t.test1();
}
catch(InterruptedException e){
System.out.println("exception caught test1");
}
}
}
class MyThread2 extends Thread{
Test t;
MyThread2(String name, Test t){
super(name);
this.t = t;
}
public void run(){
try{
t.test2();
}
catch(InterruptedException e){
System.out.println("exception caught test2");
}
}
}
class Lock1 extends ReentrantLock{
}
public class Main{
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
MyThread1 t1 = new MyThread1("thread1",t);
MyThread2 t2 = new MyThread2("thread2",t);
t1.start();
System.out.println("Before interrupt Hello....");
t1.interrupt();
System.out.println("After t1.interrupt Hello and before t2.start()....");
t2.start();
System.out.println("After t2.start Hello but before t2.interrupt....");
t2.interrupt();
System.out.println("After t2.interrupt Hello....");
System.out.println("Main Hello....");
System.out.println("Main Hello....");
System.out.println("Main Hello....");
}
}
Последние синхронизированные блоки synchronized(l)
в test1() and test2()
методы класса Test
выполняются, поскольку они содержат монитор в l (как используемое синхронизированное ключевое слово) илиблокировка l (как потоки называются l.lockInterruptibly();
) перед входом в синхронизированные блоки?
Причина, по которой я спрашиваю, удерживает ли она монитор l или блокировка l, заключается в том, что в примере ниже:
import java.util.concurrent.locks.*;
class Lock1 extends ReentrantLock{
}
class Main{
public void test() throws InterruptedException{
synchronized(this){
Lock1 m = new Lock1();
System.out.println("line 1");
m.lock();
System.out.println(m.getHoldCount());
System.out.println(m.isHeldByCurrentThread());
System.out.println("line 2");
m.wait();
System.out.println("line 3");
}
}
public static void main(String[] args) throws InterruptedException{
Main t1 = new Main();
t1.test();
}
}
Несмотря на то, что main
поток содержит lock of object m(m.lock())
, но он дает IllegalMonitorStateException , поскольку в нем нет monitor of object m
.
Надеюсь, мой вопрос легче понять.