ReentrantLock允许线程多次进入对资源锁定,
这在执行/效率/功能方面有什么好处?
请参阅此链接,https://www.geeksforgeeks.org/reentrant-lock-java/
我不明白使用内锁的意义,因为一旦外锁被任何线程获取,就不会有其他线程进入外锁之后的部分(直到时间锁被这个线程持有为止),而且可以肯定的是,外锁之后/之后的部分一次只会被一个线程执行,那么内锁的意义是什么,这意味着多次进入锁的意义是什么?
代码:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
class worker implements Runnable
{
String name;
ReentrantLock re;
public worker(ReentrantLock rl, String n)
{
re = rl;
name = n;
}
public void run()
{
boolean done = false;
while (!done)
{
//Getting Outer Lock
boolean ans = re.tryLock();
// Returns True if lock is free
if(ans)
{
try
{
Date d = new Date();
SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
System.out.println("task name - "+ name
+ " outer lock acquired at "
+ ft.format(d)
+ " Doing outer work");
Thread.sleep(1500);
// Getting Inner Lock
re.lock();
try
{
d = new Date();
ft = new SimpleDateFormat("hh:mm:ss");
System.out.println("task name - "+ name
+ " inner lock acquired at "
+ ft.format(d)
+ " Doing inner work");
System.out.println("Lock Hold Count - "+ re.getHoldCount());
Thread.sleep(1500);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
finally
{
//Inner lock release
System.out.println("task name - " + name +
" releasing inner lock");
re.unlock();
}
System.out.println("Lock Hold Count - " + re.getHoldCount());
System.out.println("task name - " + name + " work done");
done = true;
}
catch(InterruptedException e)
{
e.printStackTrace();
}
finally
{
//Outer lock release
System.out.println("task name - " + name +
" releasing outer lock");
re.unlock();
System.out.println("Lock Hold Count - " +
re.getHoldCount());
}
}
else
{
System.out.println("task name - " + name +
" waiting for lock");
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
public class test
{
static final int MAX_T = 2;
public static void main(String[] args)
{
ReentrantLock rel = new ReentrantLock();
ExecutorService pool = Executors.newFixedThreadPool(MAX_T);
Runnable w1 = new worker(rel, "Job1");
Runnable w2 = new worker(rel, "Job2");
Runnable w3 = new worker(rel, "Job3");
Runnable w4 = new worker(rel, "Job4");
pool.execute(w1);
pool.execute(w2);
pool.execute(w3);
pool.execute(w4);
pool.shutdown();
}
}发布于 2019-01-08 16:43:33
我认为解释它是如何工作的是多余的,我们应该只使用lock()或tryLock()方法中的一个:
如果您的线程有多个任务要执行,其中一些任务独立于锁,那么您应该使用tryLock()。如果线程需要执行的所有任务都依赖于锁,那么应该使用lock()。
也就是说,当线程拥有或能够获得独立于锁获取的额外工作时,您应该使用tryLock()而不是lock()。
-可选:
假设您有四个任务,1到3由具有两个工作线程A和B的线程池执行。任务1和2共享一个资源,每次必须由一个线程访问,以防止损坏。
现在,如果你只是在没有试用的情况下锁定,你可能会遇到以下情况:
请注意,lock()挂起线程,直到锁被释放,因此线程B在线程A释放锁之前是完全无用的。线程B可以启动任务3,而不是等待锁,并在此期间完成它。
使用try-lock的算法可以像这样执行:
请注意,tryLock()不挂起调用线程,因此可以跳过阻塞任务,而线程B执行非阻塞任务。如果任务1和2很长,并且还有其他几个短的非阻塞任务,则它们都可以在任务1完成或任务2开始之前完成。
当然,实现线程池和任务管理比普通的锁定要复杂一些:任务可能必须挂起并返回到池中;当任何锁被释放时,休眠的空闲线程应该被唤醒。
如果您有许多非阻塞任务(或者至少不是在同一个锁上阻塞)以及一些阻塞任务,那么这是值得的,但是如果所有任务都阻塞在同一资源上,那么从一开始就不值得实现多线程。
发布于 2019-01-08 17:15:23
假设在一个类中有两个方法m1和m2,这两个方法都已同步,并且m2正在调用m1。在这种情况下,如果线程a已经获得了m1上的锁,并且不允许再次获得锁,那么thresad将继续等待调用m2 (因为它已经拥有了锁)
更多详细信息:
https://stackoverflow.com/questions/18596080/java-concurrent-reentrantlock-why-we-want-to-acquire-the-same-lock-multiple-ti
https://stackoverflow.com/questions/54087766
复制相似问题