多线程同步工具——Lock
本文原创,转载请注明出处。
参考文章:
锁分独占锁与共享锁,公平锁与非公平锁,悲观锁与乐观锁,可重入锁与不可重入锁,相关概念可查看其它文章。
Lock操作:加锁(lock),解锁(unlock),创建条件对象(newCondition)。
Condition操作:等待(await),通知(signal)。
ReentrantLock:是一个可重入锁,独占锁,由构造参数决定是公平锁还是非公平锁。
ReadWriteLock的操作就是获取读取锁与改写锁。
ReentrantReadWriteLock:它的读取锁与改写锁都是可重入锁,并且由构造参数决定是公平锁还是非公平锁。
StampedLock:是Java8增加的锁,它不支持重入,也不支持Condition。相关文章《深入理解StampedLock及其实现原理》
ReentrantLock的源码分析:
/**
* @since 1.5
* @author Doug Lea
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L; private final Sync sync; public ReentrantLock() {
// 默认使用非公平锁
sync = new NonfairSync();
} public ReentrantLock(boolean fair) {
// 由参数决定使用公平锁还是非公平锁
sync = fair ? new FairSync() : new NonfairSync();
} abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L; abstract void lock(); final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 判断锁是否未被持有
if (c == 0) {
// 尝试占用锁
if (compareAndSetState(0, acquires)) {
// 占用成功后,更新锁所属线程为当前线程
setExclusiveOwnerThread(current);
// 返回占用成功
return true;
}
}
// 如果锁已被占用,判断当前线程是否持有锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
// 不允许锁被释放,否则视为系统错误
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 更新锁的持有次数
setState(nextc);
// 返回占用成功
return true;
}
// 返回占用失败
return false;
} protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 不允许当前线程释放其它线程持有的锁,否则抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 判断锁是否达到释放值
if (c == 0) {
// 标记锁需要释放
free = true;
// 清空锁的所属线程
setExclusiveOwnerThread(null);
}
// 更新锁的持有次数
setState(c);
// 返回锁是否达到释放值而被释放,否则未释放。
return free;
} protected final boolean isHeldExclusively() {
// 返回当前线程是否持有锁
return getExclusiveOwnerThread() == Thread.currentThread();
} final Thread getOwner() {
// 返回锁所属线程
return getState() == 0 ? null : getExclusiveOwnerThread();
} final int getHoldCount() {
// 如果当前线程未持有锁,则返回0;如果当前线程持有锁,则返回持有的次数。
return isHeldExclusively() ? getState() : 0;
} final boolean isLocked() {
// 返回锁是否已经被占用
return getState() != 0;
} final ConditionObject newCondition() {
return new ConditionObject();
}
} static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L; final void lock() {
// 尝试占用锁
if (compareAndSetState(0, 1))
// 占用成功后,更新锁所属线程为当前线程
setExclusiveOwnerThread(Thread.currentThread());
else
// 占用失败后,通过正常程序获取锁
acquire(1);
} protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
} static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L; final void lock() {
// 正常程序获取锁
acquire(1);
} protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 判断锁是否未被持有
if (c == 0) {
// 如果队列为空或队头为当前线程时,就尝试占用锁
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
// 占用成功后,更新锁所属线程为当前线程
setExclusiveOwnerThread(current);
// 返回占用成功
return true;
}
}
// 如果锁已被占用,判断当前线程是否持有锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
// 不允许锁被释放,否则视为系统错误
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
// 更新锁的持有次数
setState(nextc);
// 返回占用成功
return true;
}
// 返回占用失败
return false;
}
} public void lock() {
// 获取锁
sync.lock();
} public void lockInterruptibly() throws InterruptedException {
// 获取锁,可被中断
sync.acquireInterruptibly(1);
} public boolean tryLock() {
// 强制使用非公平方式获取锁
return sync.nonfairTryAcquire(1);
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
// 尝试在指定时间内获取锁,可被中断
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
} public void unlock() {
// 释放锁
sync.release(1);
} public int getHoldCount() {
// 如果当前线程未持有锁,则返回0;如果当前线程持有锁,则返回持有的次数。
return sync.getHoldCount();
} public boolean isHeldByCurrentThread() {
// 返回当前线程是否持有锁
return sync.isHeldExclusively();
} public boolean isLocked() {
// 返回锁是否已经被占用
return sync.isLocked();
} public final boolean isFair() {
// 返回是否公平锁
return sync instanceof FairSync;
} protected Thread getOwner() {
// 返回锁的所属线程
return sync.getOwner();
} public final boolean hasQueuedThreads() {
// 返回队列中是否还有线程,即是否队列不为空
return sync.hasQueuedThreads();
} public final boolean hasQueuedThread(Thread thread) {
// 返回目标线程是否在队列中
return sync.isQueued(thread);
} public final int getQueueLength() {
// 返回队列长度
return sync.getQueueLength();
} protected Collection<Thread> getQueuedThreads() {
// 返回队列中的所有线程
return sync.getQueuedThreads();
} public Condition newCondition() {
return sync.newCondition();
} public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
} public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
} protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
} public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]");
}
}
ReentrantReadWriteLock的源码分析:
/**
* @since 1.5
* @author Doug Lea
*/
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
private static final long serialVersionUID = -6992448646407690164L;
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync; public ReentrantReadWriteLock() {
this(false);
} public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
} public ReentrantReadWriteLock.WriteLock writeLock() {
return writerLock;
} public ReentrantReadWriteLock.ReadLock readLock() {
return readerLock;
} abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L; static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; static int sharedCount(int c) {
// 使用高16位存储共享锁的共享次数
return c >>> SHARED_SHIFT;
} static int exclusiveCount(int c) {
// 使用低16位存储独占锁被持有次数
return c & EXCLUSIVE_MASK;
} static final class HoldCounter {
int count = 0;
final long tid = Thread.currentThread().getId();
} static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();
}
} private transient ThreadLocalHoldCounter readHolds; private transient HoldCounter cachedHoldCounter; private transient Thread firstReader = null;
private transient int firstReaderHoldCount; Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
} abstract boolean readerShouldBlock(); abstract boolean writerShouldBlock(); protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
// 是否存在锁
if (c != 0) {
// 如果不存在独占锁,或当前线程并不是独占锁的所属线程,则返回获取失败
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 如果累加后的持有次数,达到最大值时,则系统错误
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 更新独占锁被当前钱程持有的次数
setState(c + acquires);
// 返回获取成功
return true;
}
// 如果是公平策略,就需要当前线程是队头,非公平策略不需要。然后尝试占用锁
if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
// 返回占用失败
return false;
// 占用成功后,更新独占锁的所属线程为当前线程
setExclusiveOwnerThread(current);
// 返回占用成功
return true;
} protected final boolean tryRelease(int releases) {
// 不允许当前线程释放其它线程持有的独占锁,否则抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
// 如果独占锁的持有次数达到释放值,就清空独占锁的所属线程
if (free)
setExclusiveOwnerThread(null);
// 更新独占锁被当前钱程持有的次数
setState(nextc);
// 返回独占锁是否已经被释放
return free;
} protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// 如果存在独占锁,并且该独占锁并不属于当前线程,就返回获取失败。
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
// 如果是公平策略,就需要当前线程是队头,如果是非公平策略,就需要队头是以共享方式取锁。
// 然后还需要共享次数未达到最大值
// 如果前面条件满足后,就尝试占用锁(注:c + SHARED_UNIT表示增加1)
if (!readerShouldBlock() && r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)) {
// 如果首次占用共享锁,就记录首个占用共享锁的线程和占用次数
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
}
// 如果不是首次占用,但当前线程就是那个首次占用共享锁的线程时,就增加记录次数
else if (firstReader == current) {
firstReaderHoldCount++;
}
else {
// 从缓存或本地变量中获取计数器
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != current.getId())
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
// 更新当前线程所占用共享锁的次数
rh.count++;
}
// 返回占用成功
return 1;
}
return fullTryAcquireShared(current);
} final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
// 判断是否存在独占锁
if (exclusiveCount(c) != 0) {
// 如果该独占锁并不属于当前线程,就返回获取失败。
if (getExclusiveOwnerThread() != current)
return -1;
} else {
// 现在不存在独占锁,如果在公平策略下,当前线程不是队头,如果在非公平策略下,队头是以独占方式取锁
// 也不是首个占用共享锁的线程,也未有占用共享锁的记录在
if (readerShouldBlock() && firstReader != current) {
// 从缓存或本地变量中获取计数器
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != current.getId()) {
rh = readHolds.get();
if (rh.count == 0)
readHolds.remove();
}
}
// 如果记录为0,就返回占用失败
if (rh.count == 0)
return -1;
}
} // 现在:
// 存在独占锁,并且当前线程是独占锁的所属线程
// 不存在独占锁,当前线程有占用共享锁的记录在
// 不存在独占锁,非公平策略,需要队头是以共享取锁才能插队占用共享锁
// 不存在独占锁,公平策略,需要当前线程位于队头才能占用共享锁(即不能插队) // 不允许共享次数达到最大值,否则系统错误
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 尝试占用共享锁(注:c + SHARED_UNIT表示增加1)
if (compareAndSetState(c, c + SHARED_UNIT)) {
// 如果首次占用共享锁,就记录首个占用共享锁的线程和占用次数
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 1;
}
// 如果不是首次占用,但当前线程就是那个首次占用共享锁的线程时,就增加记录次数
else if (firstReader == current) {
firstReaderHoldCount++;
} else {
// 从缓存或本地变量中获取计数器
if (rh == null)
rh = cachedHoldCounter;
if (rh == null || rh.tid != current.getId())
rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
// 更新当前线程所占用共享锁的次数
rh.count++;
// 缓存记录
cachedHoldCounter = rh; // cache for release
}
// 返回占用成功
return 1;
}
}
} protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
// 判断当前线程是否为第一个占用共享锁的线程
if (firstReader == current) {
// 递减占用共享锁的记录
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--;
} else {
// 从缓存或本地变量中获取计数器
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != current.getId())
rh = readHolds.get();
// 如果当前线程未有占用共享的记录,则异常
int count = rh.count;
if (count <= 1) {
readHolds.remove();
if (count <= 0)
throw unmatchedUnlockException();
}
// 递减占用共享锁的记录
--rh.count;
}
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
// 尝试递减共享锁的占用次数,如果成功,则返回共享锁的全部占用都释放。
if (compareAndSetState(c, nextc))
return nextc == 0;
}
} private IllegalMonitorStateException unmatchedUnlockException() {
return new IllegalMonitorStateException("attempt to unlock read lock, not locked by current thread");
} final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
// 是否存在锁
if (c != 0) {
int w = exclusiveCount(c);
// 如果不存在独占锁,或当前线程不是独占锁的所属线程,则返回占用失败
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 如果当前线程持有独占锁的次数达到最大值,则系统错误
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
// 尝试占用独占锁
if (!compareAndSetState(c, c + 1))
// 近回占用失败
return false;
// 占用成功后,更新独占锁的所属线程为当前线程
setExclusiveOwnerThread(current);
return true;
} final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
// 如果存在独占锁,并且当前线程不是独占锁的所属线程,就返回占用失败
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
return false;
int r = sharedCount(c);
// 如果共享锁的占用次数达到最值,则系统错误
if (r == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 尝试占用共享锁
if (compareAndSetState(c, c + SHARED_UNIT)) {
// ...
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != current.getId())
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
// 返回占用成功
return true;
}
}
} protected final boolean isHeldExclusively() {
// 返回当前线程是否持有独占锁
return getExclusiveOwnerThread() == Thread.currentThread();
} final Thread getOwner() {
// 返回独占锁的所属线程
return ((exclusiveCount(getState()) == 0) ? null : getExclusiveOwnerThread());
} final int getReadLockCount() {
// 返回共享锁的占用次数
return sharedCount(getState());
} final boolean isWriteLocked() {
// 返回独占锁的占用次数
return exclusiveCount(getState()) != 0;
} final int getWriteHoldCount() {
// 如果当前线程未持有独占锁,则返回0;如果当前线程持有独占锁,则返回持有的次数。
return isHeldExclusively() ? exclusiveCount(getState()) : 0;
} final int getReadHoldCount() {
// 返回当前线程占用共享锁的次数 // 如果独占锁未被占用,则返回0
if (getReadLockCount() == 0)
return 0; // 从第一个占用共享锁记录中(缓存)获取占用次数,并返回
Thread current = Thread.currentThread();
if (firstReader == current)
return firstReaderHoldCount; // 从缓存中获取占用次数,并返回
HoldCounter rh = cachedHoldCounter;
if (rh != null && rh.tid == current.getId())
return rh.count; // 从记录中获取占用次数,并返回
int count = readHolds.get().count;
if (count == 0)
readHolds.remove();
return count;
} final int getCount() {
// 返回锁的数量
return getState();
} final ConditionObject newCondition() {
return new ConditionObject();
}
} static final class NonfairSync extends Sync {
private static final long serialVersionUID = -8159625535654395037L; final boolean writerShouldBlock() {
return false;
} final boolean readerShouldBlock() {
// 返回队头是否以独占方式获取锁
// return apparentlyFirstQueuedIsExclusive();
return false;
}
} static final class FairSync extends Sync {
private static final long serialVersionUID = -2274990926593161451L; final boolean writerShouldBlock() {
// 如果队列为空或队头为当前线程时,就返回false,否则返回true
return hasQueuedPredecessors();
} final boolean readerShouldBlock() {
// 如果队列为空或队头为当前线程时,就返回false,否则返回true
return hasQueuedPredecessors();
}
} public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
private final Sync sync; protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
} public void lock() {
sync.acquireShared(1);
} public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
} public boolean tryLock() {
// 尝试占用共享锁,并返回是否成功
return sync.tryReadLock();
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
} public void unlock() {
sync.releaseShared(1);
} public Condition newCondition() {
// 共享锁不允许创建条件对象
throw new UnsupportedOperationException();
} public String toString() {
int r = sync.getReadLockCount();
return super.toString() + "[Read locks = " + r + "]";
}
} public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync; protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
} public void lock() {
sync.acquire(1);
} public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
} public boolean tryLock() {
// 尝试占用独占锁,并返回是否成功
return sync.tryWriteLock();
} public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
} public void unlock() {
sync.release(1);
} public boolean isHeldByCurrentThread() {
// 返回当前线程是否持有独占锁
return sync.isHeldExclusively();
} public int getHoldCount() {
// 如果当前线程未持有独占锁,则返回0;如果当前线程持有独占锁,则返回持有的次数。
return sync.getWriteHoldCount();
} public Condition newCondition() {
return sync.newCondition();
} public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]");
}
} public final boolean isFair() {
// 返回是否公平锁
return sync instanceof FairSync;
} protected Thread getOwner() {
// 返回独占锁的所属线程
return sync.getOwner();
} public int getReadLockCount() {
// 返回共享锁的占用次数
return sync.getReadLockCount();
} public boolean isWriteLocked() {
// 返回独占锁的占用次数
return sync.isWriteLocked();
} public boolean isWriteLockedByCurrentThread() {
// 返回当前线程是否持有独占锁
return sync.isHeldExclusively();
} public int getWriteHoldCount() {
// 如果当前线程未持有独占锁,则返回0;如果当前线程持有独占锁,则返回持有的次数。
return sync.getWriteHoldCount();
} public int getReadHoldCount() {
// 返回当前线程占用共享锁的次数
return sync.getReadHoldCount();
} protected Collection<Thread> getQueuedWriterThreads() {
// 返回队列中以独占模式获取锁的所有线程
return sync.getExclusiveQueuedThreads();
} protected Collection<Thread> getQueuedReaderThreads() {
// 返回队列中以共享模式获取锁的所有线程
return sync.getSharedQueuedThreads();
} public final boolean hasQueuedThreads() {
// 返回队列中是否还有线程,即是否队列不为空
return sync.hasQueuedThreads();
} public final boolean hasQueuedThread(Thread thread) {
// 返回目标线程是否在队列中
return sync.isQueued(thread);
} public final int getQueueLength() {
// 返回队列长度
return sync.getQueueLength();
} protected Collection<Thread> getQueuedThreads() {
// 返回队列中的所有线程
return sync.getQueuedThreads();
} public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync
.hasWaiters((AbstractQueuedSynchronizer.ConditionObject) condition);
} public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync
.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject) condition);
} protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync
.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject) condition);
} public String toString() {
int c = sync.getCount();
int w = Sync.exclusiveCount(c);
int r = Sync.sharedCount(c); return super.toString() + "[Write locks = " + w + ", Read locks = " + r + "]";
}
}
多线程同步工具——Lock的更多相关文章
- Java多线程同步工具类之CountDownLatch
在过去我们实现多线程同步的代码中,往往使用join().wait().notiyAll()等线程间通信的方式,随着JUC包的不断的完善,java为我们提供了丰富同步工具类,官方也鼓励我们使用工具类来实 ...
- c#多线程同步之lock
一提起lock,想必大家都很熟悉,因为它易用,顾名思义,就是一把锁,常用于多线程的同步,一次只允许一个线程进入.最近遇到一个很诡异的bug. private static readonly objec ...
- Java多线程同步工具类之CyclicBarrier
一.CyclicBarrier使用 CyclicBarrier从字面上可以直接理解为线程运行的屏障,它可以让一组线程执行到一个共同的屏障点时被阻塞,直到最后一个线程执行到指定位置,你设置的执行线程就会 ...
- Java多线程同步工具类之Semaphore
Semaphore信号量通常做为控制线程并发个数的工具来使用,它可以用来限制同时并发访问资源的线程个数. 一.Semaphore使用 下面我们通过一个简单的例子来看下Semaphore的具体使用,我们 ...
- 多线程同步工具——volatile变量
关于volatile,找了一堆资料看,看完后想找一个方法去做测试,测了很久,感觉跟没有一样. 这本书<深入理解Java内存模型>,对volatile描述中有这样一个比喻的说法,如下代码所示 ...
- 多线程同步工具——CAS原子变量
这是我参考的一篇文章<基于CAS的乐观锁实现>,讲述的是一种需要CPU支持的执行技术CAS(Compare and Swap). 首先理解什么是原子性操作,意思是不能再拆分的操作,例如改写 ...
- python多线程同步机制Lock
#!/usr/bin/env python# -*- coding: utf-8 -*- import threadingimport time value = 0lock = threading.L ...
- 多线程同步工具——LockSupport
用例1:子线程等待主线程发放许可! public static void main(String[] args) { Thread thread = new Thread(){ public void ...
- c#中多线程同步Lock(锁)的研究以及跨线程UI的操作
本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧. 其实多线程的同步,使用 ...
随机推荐
- IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法
直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...
- 透过WinDBG的视角看String
摘要 : 最近在博客园里面看到有人在讨论 C# String的一些特性. 大部分情况下是从CODING的角度来讨论String. 本人觉得非常好奇, 在运行时态, String是如何与这些特性联系上的 ...
- Java数据库连接技术——JDBC
大家好,今天我们学习了Java如何连接数据库.之前学过.net语言的数据库操作,感觉就是一通百通,大同小异. JDBC是Java数据库连接技术的简称,提供连接各种常用数据库的能力. JDBC API ...
- CSS 选择器及各样式引用方式
Css :层叠样式表 (Cascading Style Sheets),定义了如何显示HTML元素. 目录 1. 选择器的分类:介绍ID.class.元素名称.符合.层次.伪类.属性选择器. 2. 样 ...
- Android 获取系统相册中的所有图片
Android 提供了API可获取到系统相册中的一些信息,主要还是通过ContentProvider 来获取想要的内容. 代码很简单,只要熟悉ContentProvider 就可以了. public ...
- AFNetworking 3.0 源码解读(十一)之 UIButton/UIProgressView/UIWebView + AFNetworking
AFNetworking的源码解读马上就结束了,这一篇应该算是倒数第二篇,下一篇会是对AFNetworking中的技术点进行总结. 前言 上一篇我们总结了 UIActivityIndicatorVie ...
- [内核笔记1]内核文件结构与缓存——inode和对应描述
由来:公司内部外网记录日志的方式现在都是通过Nginx模块收到数据发送到系统消息队列,然后由另外一个进程来从消息队列读取然后写回磁盘这样的操作,尽量的减少Nginx的阻塞. 但是由于System/V消 ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- BPM配置故事之案例1-配置简单流程
某天,Boss找到了信息部工程师小明. Boss:咱们新上了H3 BPM,你研究研究把现在的采购申请流程加上去吧,这是采购申请单. 小明:好嘞 采购申请单 小明回去后拿着表单想了想,开始着手配置. 他 ...
- 一个软件开发者的BPM之路
我是小林,一名普通的软件工程师,从事BPM(业务流程管理)软件开发工作.我没有几十年的技术底蕴,无法像大牛们一样高谈阔论,品评BPM开发之道:也不是资深的流程管理专家,能与大家分析流程管理的时弊.我只 ...