Skip to main content

java juc

· 5 min read

背景

了解java容器类

juc主要类

Collection 接口:

描述
List列表
Queue队列
Set集合

Map接口:

描述线程安全是否可以由null值
HashMaphanshmap
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

parkunpark 使用的是pthread_cond_waitpthread_cond_notify

condition variable vs semaphore

信号量semaphore

  • 描述的是state 计数器 state 描述的是资源数
  • state>0 表示还有资源
  • state<= 0 表示没有资源

条件变量condition variable:

  • 更多是偏向描述生产者和消费者的等待

条件变量: 为了解决等待 信号量: 为了解决线程/进程同步(线程/进程通信)

区别:

条件变量: queue + block 信号量: state+block

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_waitpthread_cond_signal好一点

相关阅读