背景
了解java容器类
juc主要类
Collection 接口:
类 | 描述 |
---|---|
List | 列表 |
Queue | 队列 |
Set | 集合 |
Map接口:
类 | 描述 | 线程安全 | 是否可以由null值 |
---|---|---|---|
HashMap | hanshmap | 否 | 是 |
PriorityQueue | 优先队列,implement Queue | 否 | 否,因为要排序,null会抛异常 |
HashSet | 一个set的实现 | 否 | 是 This class permits the null element. |
aqs
aqs 主要是提供了三个property:
- state: int 表示资源 ,维护一个volatile 的int
- queue: 来block队列,一个普通队列,用来塞线程Thread这个变量
- block: 获取不到资源就阻塞 , 使用park和unpark, jni实现
block
park 和unpark 使用的是pthread_cond_wait 和pthread_cond_notify
park 源码分析
// Parker::park decrements count if > 0, else does a condvar wait. Unpark
// sets count to 1 and signals condvar. Only one thread ever waits
// on the condvar. Contention seen when trying to park implies that someone
// is unparking you, so don't wait. And spurious returns are fine, so there
// is no need to track notifications.
void Parker::park(bool isAbsolute, jlong time) {
// Optional fast-path check:
// Return immediately if a permit is available.
// We depend on Atomic::xchg() having full barrier semantics
// since we are doing a lock-free update to _counter.
if (Atomic::xchg(&_counter, 0) > 0) return;
JavaThread *jt = JavaThread::current();
// Optional optimization -- avoid state transitions if there's
// an interrupt pending.
if (jt->is_interrupted(false)) {
return;
}
// Next, demultiplex/decode time arguments
struct timespec absTime;
if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all
return;
}
if (time > 0) {
to_abstime(&absTime, time, isAbsolute, false);
}
// Enter safepoint region
// Beware of deadlocks such as 6317397.
// The per-thread Parker:: mutex is a classic leaf-lock.
// In particular a thread must never block on the Threads_lock while
// holding the Parker:: mutex. If safepoints are pending both the
// the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
ThreadBlockInVM tbivm(jt);
// Can't access interrupt state now that we are _thread_blocked. If we've
// been interrupted since we checked above then _counter will be > 0.
// Don't wait if cannot get lock since interference arises from
// unparking.
if (pthread_mutex_trylock(_mutex) != 0) {
return;
}
int status;
if (_counter > 0) { // no wait needed
_counter = 0;
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "invariant");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
return;
}
OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
assert(_cur_index == -1, "invariant");
if (time == 0) {
_cur_index = REL_INDEX; // arbitrary choice when not timed
status = pthread_cond_wait(&_cond[_cur_index], _mutex);
assert_status(status == 0 MACOS_ONLY(|| status == ETIMEDOUT),
status, "cond_wait");
}
else {
_cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
status = pthread_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
assert_status(status == 0 || status == ETIMEDOUT,
status, "cond_timedwait");
}
_cur_index = -1;
_counter = 0;
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "invariant");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
}
aqs 内容
aqs 主要包括三个内容:
- state
- queue
- park/unpark
state
描述了资源的数量,一般是用这个来判断是否应该阻塞, 一般是state=0 就要被唤醒或者被注释
queue
为了唤醒的时候可以找到下一个需要被唤醒的元素
park/unpark
LockSupport 的这两个函数,主要是实现了线程的阻塞和唤醒,在linux下是封装了pthread_cond_wait 和pthread_cond_signal.除此之外,为了避免丢失通知,多了一个_counter
变量,比普通的pthread_cond_wait
和pthread_cond_signal
好一点