ReentrantLock的trylock方法不允许多线程轮流
ReentrantLock's trylock method not allowing turn taking of multiple threads
我正在研究 MultiThreading
概念。我遇到了 ReentrantLock
。它有方法 lock
和 trylock
。当我进一步研究它们时,我了解到它们可以用来代替 synchronized
关键字块或方法。所以我用 Kathie Sierra 书中给出的 classic 示例 AccountDanger
再次尝试了它们。我观察到 lock
方法确实允许与其他线程轮流使用。但是 trylock
布尔方法不允许轮流使用其他线程。下面的示例:
用lock
方法
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
lock.lock();
try{
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}finally{
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
以上带有 lock
方法的代码允许 Mark
和 Phew
线程轮流。
用trylock
方法
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
try{
if(lock.tryLock()){
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}
}
finally {
if(lock.tryLock()){
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
以上代码不允许 Phew
线程轮流使用 Thread.sleep()
方法。
帐号class
package p1;
public class Account{
private int balance = 100;
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public void withdraw(int amount){
this.balance = this.balance - amount;
}
}
尽管毫无疑问,这两种方法都可以防止余额变为负数。但我不明白为什么 trylock
对进程如此认真以至于它不允许其他线程进入执行之间,即使在内部调用 Thread.sleep
也是如此。即使我在 Thread.sleep
的 catch 块之后的 finally
块中使用 lock.unlock
语句,也只有 mark
线程正在执行。
您的基本误解是 trylock
没有获得锁,但确实如此;正如我在评论中所述,trylock
等同于 lock
除了如果无法获得锁它不会阻塞。
你的情况是这样的:
- Mark线程启动并获得锁,然后休眠0.,5秒
- 此时,Phew 线程启动。它试图获得锁但失败了,因为 Mark 拥有它。
- Phew 开始下一个循环迭代; Phew 再次尝试获取锁,但失败了。这种情况发生在循环 运行.
的 10 次
- 循环结束;这将退出线程的
run
方法并终止 Phew 线程。
- Mark 线程的休眠结束。
- finally 块释放锁。
- Mark 开始下一个循环迭代。它尝试获取锁并成功(周围没有其他人再获取锁)。同样,这种情况总共发生了 10 次。
我正在研究 MultiThreading
概念。我遇到了 ReentrantLock
。它有方法 lock
和 trylock
。当我进一步研究它们时,我了解到它们可以用来代替 synchronized
关键字块或方法。所以我用 Kathie Sierra 书中给出的 classic 示例 AccountDanger
再次尝试了它们。我观察到 lock
方法确实允许与其他线程轮流使用。但是 trylock
布尔方法不允许轮流使用其他线程。下面的示例:
用lock
方法
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
lock.lock();
try{
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}finally{
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
以上带有 lock
方法的代码允许 Mark
和 Phew
线程轮流。
用trylock
方法
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
try{
if(lock.tryLock()){
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}
}
finally {
if(lock.tryLock()){
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
以上代码不允许 Phew
线程轮流使用 Thread.sleep()
方法。
帐号class
package p1;
public class Account{
private int balance = 100;
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public void withdraw(int amount){
this.balance = this.balance - amount;
}
}
尽管毫无疑问,这两种方法都可以防止余额变为负数。但我不明白为什么 trylock
对进程如此认真以至于它不允许其他线程进入执行之间,即使在内部调用 Thread.sleep
也是如此。即使我在 Thread.sleep
的 catch 块之后的 finally
块中使用 lock.unlock
语句,也只有 mark
线程正在执行。
您的基本误解是 trylock
没有获得锁,但确实如此;正如我在评论中所述,trylock
等同于 lock
除了如果无法获得锁它不会阻塞。
你的情况是这样的:
- Mark线程启动并获得锁,然后休眠0.,5秒
- 此时,Phew 线程启动。它试图获得锁但失败了,因为 Mark 拥有它。
- Phew 开始下一个循环迭代; Phew 再次尝试获取锁,但失败了。这种情况发生在循环 运行. 的 10 次
- 循环结束;这将退出线程的
run
方法并终止 Phew 线程。 - Mark 线程的休眠结束。
- finally 块释放锁。
- Mark 开始下一个循环迭代。它尝试获取锁并成功(周围没有其他人再获取锁)。同样,这种情况总共发生了 10 次。