Java多线程学习笔记18之Lock的使用

详细代码见:github代码地址

 

本节内容:

    公平锁和非公平锁以及ReentrantLock常用方法的使用

1) 公平锁和非公平锁

2) getHoldCount()、getQueueLength()、getWaitQueueLength()

3) hasQueueThread()、hasQueueThreads()、hasWaiters()

4) lockInterruptibly()、tryLock()、tryLock(long timeout, TimeUnit unit)

 

3.公平锁和非公平锁以及常用方法的使用

(1) 公平锁和非公平锁
公平锁和非公平锁:

    锁Lock分为"公平锁"和"非公平锁",公平锁表示线程获取锁的顺序是按照线程

加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。而非公平锁就是一种

获得锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得

到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平了。

默认情况下ReentrantLock的构造函数不传递参数是非公平锁false,如果传递参数则指定是否公平。
对于这两种锁的支持,ReentrantLock实际上是内建了两个锁来分分别实现这两种锁,一个叫FairSync
(公平锁),一个叫NonFairSync(非公平锁).由于这是多线程知识,我后面会开一个高并发专栏,讲讲
源代码及一些框架的用法。


举例:

package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

import java.util.concurrent.locks.ReentrantLock;

public class Service {
	
	private ReentrantLock lock;
	
	public Service(boolean isFair) {
		super();
		lock = new ReentrantLock(isFair);
	}
	
	public void serviceMethod() {
		try {
			lock.lock();
			System.out.println("ThreadName=" + Thread.currentThread().getName()
					+ "获得锁定");
		} finally {
			// TODO: handle finally clause
			lock.unlock();
		}
	}
}


package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

public class RunFair {

	public static void main(String[] args) throws InterruptedException {
		final Service service = new Service(true);

		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("★线程" + Thread.currentThread().getName()
						+ "运行了");
				service.serviceMethod();
			}
		};

		Thread[] threadArray = new Thread[10];
		for (int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		for (int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
	}
}
/*
result:
★线程Thread-1运行了
★线程Thread-8运行了
★线程Thread-6运行了
★线程Thread-7运行了
★线程Thread-3运行了
★线程Thread-5运行了
★线程Thread-0运行了
★线程Thread-4运行了
★线程Thread-2运行了
★线程Thread-9运行了
ThreadName=Thread-0获得锁定
ThreadName=Thread-4获得锁定
ThreadName=Thread-6获得锁定
ThreadName=Thread-8获得锁定
ThreadName=Thread-2获得锁定
ThreadName=Thread-1获得锁定
ThreadName=Thread-5获得锁定
ThreadName=Thread-3获得锁定
ThreadName=Thread-7获得锁定
ThreadName=Thread-9获得锁定
*/

可以看到大体上是这个顺序,有兴趣可以去读读源码

package chapter04.section01.thread_4_1_9.project_1_Fair_noFair_test;

public class RunNotFair {
	public static void main(String[] args) {
		final Service service = new Service(false);
		
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("★线程" + Thread.currentThread().getName()
						+ "运行了");
				service.serviceMethod();
			}
		};
		
		Thread[] threadArray = new Thread[10];
		for(int i = 0; i < 10; i++) {
			threadArray[i] = new Thread(runnable);
		}
		
		for(int i = 0; i < 10; i++) {
			threadArray[i].start();
		}
	}
}
/*
result:
★线程Thread-1运行了
★线程Thread-6运行了
★线程Thread-4运行了
★线程Thread-2运行了
★线程Thread-0运行了
★线程Thread-5运行了
★线程Thread-3运行了
★线程Thread-7运行了
★线程Thread-9运行了
ThreadName=Thread-9获得锁定
ThreadName=Thread-7获得锁定
ThreadName=Thread-3获得锁定
ThreadName=Thread-1获得锁定
ThreadName=Thread-0获得锁定
ThreadName=Thread-2获得锁定
ThreadName=Thread-5获得锁定
ThreadName=Thread-6获得锁定
ThreadName=Thread-4获得锁定
★线程Thread-8运行了
ThreadName=Thread-8获得锁定
*/

可以看到非公平锁THread-1先执行了竟然是第一个获得锁。


4. ReentrantLock实例的方法的使用

(1) 方法getHoldCount(), getQueueLength()和getWaitQueueLength()的测试

1) getHoldCount()
int getHoldCount()的作用是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数
文档:

public int getHoldCount​()
Queries the number of holds on this lock by the current thread.
A thread has a hold on a lock for each lock action that is not matched by an unlock 
action.
查询当前线程对该锁的持有数量
对于每个锁操作,线程都持有一个锁,而锁操作与解锁操作不匹配

The hold count information is typically only used for testing and debugging purposes. 
For example, if a certain section of code should not be entered with the lock already 
held then we can assert that fact:
拥有锁的信息通常只用于测试和调试目的
例如,如果不应该进入已经持有锁的代码段,我们可以断言:
(在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个
boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告并退出。)
 class X {
   ReentrantLock lock = new ReentrantLock();
   // ...
   public void m() {
     assert lock.getHoldCount() == 0;
     lock.lock();
     try {
       // ... method body
     } finally {
       lock.unlo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youaresherlock

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值