同步:保证共享数据在同一时刻只被一个(使用信号量的时候可以是多个)线程使用
互斥:互斥是实现同步的手段,同步是互斥要实现的目的
操作系统层面的概念:
- 临界区
- 互斥量
- 信号量
- synchronized关键字经过编译后会在代码块(同步块)的前后形成monitorenter、monitorexit两个字节码指令,这两个字节码都需要一个reference类型的参数来指明要锁定和解锁的对象;
- 执行monitorenter,如果获取到对象的锁或者当前线程已经持有锁,锁计数器+1
- 如果获取对象锁失败,线程阻塞等待,直到其他线程执行monitorexit指令,释放锁资源
- 阻塞或唤醒一个线程,都需要操作系统从用户态转换为核心态,会消耗很多系统资源,所以synchronized是重量级锁
- 执行monitorexit 锁计数器 -1
下面描述来自 https://www.hollischuang.com/archives/1883
- 方法级的同步是隐式的,运行时常量池中会有一个ACC_SYNCHRONIZED标志。
- 当某个线程要访问某个方法的时候,会检查是否有ACC_SYNCHRONIZED,
- 如果有设置ACC_SYNCHRONIZED标志,需要先获取锁,然后开始执行方法,方法执行之后再释放锁。
- 这时如果其他线程来请求执行方法,会因为无法获得锁而被阻塞。
- 如果在方法执行过程中,发生了异常,并且方法内部并没有处理该异常,那么在异常被抛到方法外面之前锁会被自动释放。
https://blog.csdn.net/hduzjn/article/details/121420595
package java.util.concurrent.locks
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
public interface Lock {
// try
void lock();
// finally
void unlock();
// 获取锁的过程中可中断 synchronized不可以
void lockInterruptibly() throws InterruptedException;
// Acquires the lock if it is available and returns immediately with the value true.
// If the lock is not available then this method will return immediately with the value false
// This usage ensures that the lock is unlocked if it was acquired,
// and doesn't try to unlock if the lock was not acquired.
// Returns : true if the lock was acquired and false otherwise
//
boolean tryLock();
// 根据传入的时间段获取锁,在指定时间内没有获取锁则返回false,
// 如果在指定时间内当前线程未被中并断获取到锁则返回true
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
Condition newCondition();
}
2.2 Condition 接口
Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
- 替代同步方法和状态,以及监视器方法 synchronized/wait/notify/notifyAll
- await 释放锁
- signal 获取锁
A Condition instance is intrinsically bound to a lock. To obtain a Condition instance for a particular Lock instance use its newCondition() method.
- Condition和锁绑定,配合锁才能使用,通过 lock.newCondition() 获得Condition实例
public interface Condition {
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
}
2.2.1 使用例子
* class BoundedBuffer {
* final Lock lock = new ReentrantLock();
* final Condition notFull = lock.newCondition();
* final Condition notEmpty = lock.newCondition();
*
* final Object[] items = new Object[100];
* int putptr, takeptr, count;
*
* public void put(Object x) throws InterruptedException {
* lock.lock();
* try {
* while (count == items.length)
* notFull.await();
* items[putptr] = x;
* if (++putptr == items.length) putptr = 0;
* ++count;
* notEmpty.signal();
* } finally {
* lock.unlock();
* }
* }
*
* public Object take() throws InterruptedException {
* lock.lock();
* try {
* while (count == 0)
* notEmpty.await();
* Object x = items[takeptr];
* if (++takeptr == items.length) takeptr = 0;
* --count;
* notFull.signal();
* return x;
* } finally {
* lock.unlock();
* }
* }
* }
*
2.2.2 ConditionObject
Condition Queue
private static final long serialVersionUID = 1173984872572414699L;
private transient Node firstWaiter;
private transient Node lastWaiter;
https://www.cnblogs.com/zerotomax/p/8969416.html
https://blog.csdn.net/zy1994hyq/article/details/84562475
- 默认是非公平锁
调用内部的sync的方法
public void lock() {
sync.lock();
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
2.3.3 Sync / NoFairSync / FairSync
① Sync
nonfairTryAcquire
- 可重入的逻辑
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 锁没被占用 CAS 获取锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 判断获取锁的线程 是否是当前占用锁的线程
else if (current == getExclusiveOwnerThread()) {
// 如果是 state =state + acquires
// 可重入在此展现
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
② NonfairSync 非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
// 判断state是否是0(表示当前锁未被占用),如果是0则把它置为1,然后设置独占线程为当前线程
// 非公平的体现 ,占用锁的线程释放了锁,state状态变成0,此时如果有一个新来的线程正好调用lock方法,
// 那么它会在 wait queue队列 中等待的线程 之前获得锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 否则执行 AQS 的 acquire方法
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
③ FairSync 公平锁
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
// 这里没有 if else判断 state的状态,然后获取锁
final void lock() {
// 直接调用 acquire ,这样所有线程都要在 wait queue 里排队
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;
}
}



